elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Arreglado, de nuevo, el registro del warzone (wargame) de EHN


  Mostrar Temas
Páginas: [1] 2 3
1  Seguridad Informática / Análisis y Diseño de Malware / [SRC][C++/ASM] ClsAntiDebug en: 3 Abril 2011, 07:17 am
 Aqui les traigo una clase para colocar mecanismos contra Debuggers en nuestros codigos de una forma rapida y sencilla. Los metodos estan claros y simplemente se deben utilizar depende el metodo que deseemos utilizar para detectar los Debuggers. Estan integrados los metodos de deteccion a traves del PEB, del NTGlobal, utilizando los nombres comunes de los procesos de OllyDBG, IDA Pro y Win32DASM. En el metodo TimeStamp deben verificar antes de dar un valor el tiempo que dura la funcion que toma como segundo parametro. Tenemos otro metodo que es el metodo Protect, el cual toma una funcion y verifica con los tres primeros metodos de deteccion para verificar que no estan siendo Debuggeados, de caso contrario ejecutara una funcion que toma como parametro.

Como lo prometido es deuda aqui van los codigos:

Código
  1. #ifndef __ClsAntiDebug__
  2. #define __ClsAntiDebug__
  3. #include <windows.h>
  4. #include <tlhelp32.h>
  5.  
  6. class ClsAntiDebug
  7. {
  8. private:
  9. bool Debugged;
  10. public:
  11. ClsAntiDebug();
  12. void __declspec() PEBDebug();
  13. void __declspec() NTGlobalDebug();
  14. void __declspec() DebuggerActive();
  15. void __declspec() TimeStamp(int time, void *func);
  16. void Protect(void *func);
  17. bool IsDebugged();
  18. };
  19. #endif

Aqui debajo estan las declaraciones de los metodos en la clase:

Código
  1. #include "AntiDebug.h"
  2.  
  3. ClsAntiDebug::ClsAntiDebug()
  4. {
  5. this->Debugged=false;
  6. }
  7.  
  8. bool ClsAntiDebug::IsDebugged()
  9. {
  10. return this->Debugged;
  11. }
  12.  
  13. void __declspec() ClsAntiDebug::PEBDebug()
  14. {
  15. __asm
  16. {
  17. _PEBLoop:
  18. push 500
  19. call dword ptr ds:[Sleep]
  20. xor edx, edx
  21. mov dl,0x30
  22. mov esi, fs:[edx]
  23. movzx eax, byte ptr[esi+2]
  24. dec eax
  25. jne _PEBLoop
  26. inc eax
  27. }
  28. this->Debugged = true;
  29. }
  30.  
  31. void __declspec() ClsAntiDebug::NTGlobalDebug()
  32. {
  33. __asm
  34. {
  35. _NTLoop:
  36. push 500
  37. call dword ptr ds:[Sleep]
  38. xor edx, edx
  39. mov dl,0x30
  40. mov esi, fs:[edx]
  41. movzx eax, byte ptr[esi+0x68]
  42. and eax,eax
  43. je _NTLoop
  44. xor eax,eax
  45. inc eax
  46. }
  47. this->Debugged = true;
  48. }
  49.  
  50. void __declspec() ClsAntiDebug::DebuggerActive()
  51. {
  52. HANDLE hProcSnap;
  53. PROCESSENTRY32 pProcess;
  54. LPTSTR Exename;
  55. int strlength;
  56. int deb[3]={18416231/*IDA Pro*/,997340682/*W32DASM*/,1853255255/*OllyDbg*/};
  57. int i;
  58. do
  59. {
  60. hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  61. pProcess.dwSize = sizeof(PROCESSENTRY32);
  62. Process32First(hProcSnap,&pProcess);
  63. do
  64. {
  65. strlength = strlen(pProcess.szExeFile);
  66. __asm
  67. {
  68. lea eax,[pProcess.szExeFile]
  69. mov ecx,dword ptr[strlength]
  70. xor edx,edx
  71. xor edi, edi
  72. push edi
  73. gethash:
  74. pop edi
  75. xor dl, byte ptr[eax+edi]
  76. rol edx,8
  77. inc edi
  78. push edi
  79. xor edi,ecx
  80. jne gethash
  81. mov [strlength],edx/*We don't need strlength, so we recycle to get
  82.     The Hash on Int Variable*/
  83. pop edi
  84. }
  85. for(i=0;i<3;i++)if (strlength==deb[i])
  86. {
  87. this->Debugged = true;
  88. __asm{jmp ___end}
  89. }
  90. }while(Process32Next(hProcSnap,&pProcess));
  91. Sleep(500);
  92. }while(1);
  93. __asm
  94. {___end:}
  95. }
  96. void __declspec() ClsAntiDebug::Protect(void *func)
  97. {
  98.  
  99. do
  100. {
  101. switch(GetTickCount()%4)
  102. {
  103. case 0:this->PEBDebug();break;
  104. case 1:this->NTGlobalDebug();break;
  105. case 2:this->DebuggerActive();break;
  106. };
  107. if (this->Debugged)
  108. {
  109. __asm
  110. {
  111. call [func]
  112. }
  113. }
  114. Sleep(500);
  115. }while(1);
  116. }
  117.  
  118. void __declspec() ClsAntiDebug::TimeStamp(int time,void *func)
  119. {
  120. __asm
  121. {
  122. rdtsc
  123. mov ebx,eax
  124. call [func]
  125. rdtsc
  126. sub eax, ebx
  127. cmp eax, [time]
  128. jna ___rtend
  129. }
  130. this->Debugged = true;
  131. __asm{___rtend: }
  132. }

Aqui tenemos una muestra de como utilizar la clase:

Código
  1. #pragma comment(linker,"/ENTRY:main")
  2.  
  3. #include "AntiDebug.h"
  4. void CALLBACK HolaMundo()
  5. {
  6. int i;
  7. i++;
  8. i++;
  9. }
  10.  
  11. int __declspec() main()
  12. {
  13.  
  14. ClsAntiDebug *Debugger=new(ClsAntiDebug);
  15. Debugger->TimeStamp(200,HolaMundo);
  16. if (Debugger->IsDebugged())MessageBox(0,"Hola","Mundo",0);
  17. Debugger->Protect(HolaMundo);
  18. return 0;
  19. }
2  Programación / .NET (C#, VB.NET, ASP) / [SRC/VB.Net]Ec2Solver en: 18 Marzo 2011, 03:53 am
Soluciona Ecuaciones de 2do Grado... contiene un modulo el cual cree especialmente para esta ocasion.

Modulo Ec2Solver
Código
  1. Module Ec2Solver
  2.    '*----------------------------------------------------------------------------------------------*
  3.    '| Author: [L]ord [R]NA                                                                         |
  4.    '| Country: Dominican Republic                                                                  |
  5.    '*----------------------------------------------------------------------------------------------*
  6.    ' Description: A Module to solve 2nd Degree Equations. The Module Ec2Solver has a Function that |
  7.    ' Get the First 3 constant value of the equation And 2 Double Variables are public in the module|
  8.    ' to get the possible values of X. If everything is Ok the Function return True and if it's     |
  9.    ' something wrong Return False.                                                                 |
  10.    '*----------------------------------------------------------------------------------------------*
  11.    '|Website: http://lordrna.co.cc/ http://foro.h-sec.org/                                         |
  12.    '|Mail: lordrna@h-sec.org                                                                       |
  13.    '*----------------------------------------------------------------------------------------------*
  14.    Public X1 As Double, X2 As Double
  15.    Dim A1 As Double, B1 As Double, C1 As Double
  16.  
  17.    Public Function Ec2Solver(ByVal A As String, ByVal B As String, ByVal C As String) As Boolean
  18.        If Double.TryParse(A, A1) And Double.TryParse(B, B1) And Double.TryParse(C, C1) Then
  19.            Ec2Solver = Ec2Solver(A1, B1, C1)
  20.        Else
  21.            Ec2Solver = False
  22.        End If
  23.    End Function
  24.  
  25.    Public Function Ec2Solver(ByVal A As Double, ByVal B As Double, ByVal C As Double) As Boolean
  26.  
  27.        Dim temp As Double
  28.        X1 = 0
  29.        X2 = 0
  30.        If A = 0 Then Ec2Solver = False
  31.        If B = 0 And A <> 0 Then
  32.            If C / A > 0 Then
  33.                Ec2Solver = False
  34.            Else
  35.                If C = 0 Then
  36.                    Ec2Solver = True
  37.                Else
  38.                    X1 = -System.Math.Sqrt(System.Math.Abs(C / A))
  39.                    X2 = System.Math.Sqrt(System.Math.Abs(C / A))
  40.                    Ec2Solver = True
  41.                End If
  42.            End If
  43.        ElseIf C = 0 Then
  44.            X1 = B / A
  45.            Ec2Solver = True
  46.        Else
  47.            temp = (System.Math.Pow(B, 2)) - 4 * A * C
  48.            If temp < 0 Then
  49.                Ec2Solver = False
  50.            Else
  51.                temp = System.Math.Sqrt(temp) / (2 * A)
  52.                X1 = -B + temp
  53.                X2 = -B - temp
  54.                Ec2Solver = True
  55.            End If
  56.        End If
  57.  
  58.    End Function
  59. End Module
  60.  

Source
Código
  1. Public Class Form1
  2.  
  3.    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  4.        A.Clear()
  5.        B.Clear()
  6.        C.Clear()
  7.        X1.Clear()
  8.        X2.Clear()
  9.    End Sub
  10.  
  11.    Private Sub A_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles A.Click
  12.        A.Text = ""
  13.    End Sub
  14.  
  15.    Private Sub B_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles B.Click
  16.        B.Text = ""
  17.    End Sub
  18.  
  19.    Private Sub C_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles C.Click
  20.        C.Text = ""
  21.    End Sub
  22.  
  23.    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
  24.        If Len(A.Text) = 0 Or A.Text = "0" Then A.Text = "1"
  25.        If Len(B.Text) = 0 Then B.Text = "0"
  26.        If Len(C.Text) = 0 Then C.Text = "0"
  27.  
  28.        If Ec2Solver.Ec2Solver(A.Text, B.Text, C.Text) = True Then
  29.            X1.Text = Str(Ec2Solver.X1)
  30.            X2.Text = Str(Ec2Solver.X2)
  31.        Else
  32.            X1.Text = "Sin Solucion"
  33.            X2.Text = "Real"
  34.        End If
  35.    End Sub
  36. End Class
3  Foros Generales / Foro Libre / Saludos desde el Hades en: 26 Febrero 2011, 02:25 am
Tengo mucho tiempo que no pasaba por aqui, se podria decir meses, pero aun no los he abandonado... aun me queda mucho por trollear. Espero que no mueran pronto...

[L]ord [R]NA ::)
4  Programación / Programación C/C++ / [SRC] ByteCounter en: 17 Enero 2011, 18:14 pm
::) Pequeño codigo en C++ que cuenta la cantidad de bytes de un archivo pasado como parametro.
 
Código
  1. #include <cstdio>
  2. #include <iostream>
  3.  
  4. void main(int argc, char *argv[])
  5. {
  6. FILE *pFile;
  7. long size;
  8. if(argc==2)
  9. {
  10. pFile = fopen(argv[1],"r");
  11. if(pFile!=NULL)
  12. {
  13. if(!fseek(pFile,0,SEEK_END))
  14. {
  15. size=ftell(pFile);
  16. fclose(pFile);
  17. std::cout<<"El tamaño total del archivo es ";
  18. std::cout<<size<<" Bytes."<<std::endl;
  19. }
  20. else std::cout<<"Sucedio un problema mientras se trataba de obtener la cantidad de bytes."<<std::endl;
  21. }
  22. else std::cout<<"Problemas con el archivo, verifique que el archivo exista."<<std::endl;
  23. }
  24.  
  25. else std::cout<<"Uso: "<<argv[0]<<" <ruta de archivo>"<<std::endl;
  26. }
  27.  

Ejemplos:
Código:
lordrna@AAO150:~/Proyectos/C++/ByteCounter$ ls
bc  bc.cpp

lordrna@AAO150:~/Proyectos/C++/ByteCounter$ ./bc bc.cpp
El tamaño total del archivo es 627 Bytes.

lordrna@AAO150:~/Proyectos/C++/ByteCounter$ ./bc cdc
Problemas con el archivo, verifique que el archivo exista.
5  Programación / Scripting / [SRC] ByteCounter en: 17 Enero 2011, 18:11 pm
Cuenta los bytes totales de un archivo.
Código
  1. #!/usr/bin/env python
  2. #coding: utf-8
  3.  
  4. import sys,os
  5.  
  6. if len(sys.argv)==2:
  7.    try:
  8.        file=open(sys.argv[1],'r')
  9.    except:
  10.        print "Problemas con el archivo, verifique el que archivo existe."
  11.        sys.exit(0)
  12.    file.seek(0,os.SEEK_END)
  13.    print "El Tama&#241;o total del archivo es",file.tell(),"Bytes."
  14.  
  15. else:
  16.     print "uso:",sys.argv[0],"<Ruta Del Archivo>"
6  Foros Generales / Foro Libre / [Aviso Global]Protesta Formal contra Elhacker.net!!! en: 26 Noviembre 2010, 13:54 pm
Felicitaciones a Azielito... Hoy llega a sus Bastardos 26
;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-) ;-)
7  Programación / Bases de Datos / Cifrar una Base de Datos. en: 17 Noviembre 2010, 09:09 am
Bueno, el caso es que tengo una aplicacion en la cual querria cifrar toda la Base de Datos o protegerla con contraseña... Alguna idea de como es posible realizar esto sin tener que cifrar directamente el archivo?, Estoy trabajando desde el FrameWork Qt con C++.
8  Foros Generales / Foro Libre / .NET Sucks en: 10 Noviembre 2010, 14:03 pm
 ;-) ;-) Felicitaciones a D4N93R... El bastardo esta de cumpleaño hoy, a menos que el facebook se equivoque  :silbar:

Vive solo 1 año mas y deja de programar en C#  :xD :xD :xD
9  Programación / Programación C/C++ / [Capitulo III]Threads. en: 28 Octubre 2010, 09:12 am
Threads

Los Threads como los procesos son mecanismos que permiten a un programa realizar mas de una accion a la vez. Como sucede con los procesos, los Threads al igual que los procesos parecen correr al mismo tiempo; El kernel de Linux los organiza de forma asincronica, interrumpiendo cada Thread durante un tiempo hasta otro tiempo, dando asi a los demas la oportunidad de ejecutarse.

Los Threads existen en conjunto con los procesos, son pequeñas porciones de ejecucion del proceso. Cuando ejecutamos un programa este crea un proceso y en ese proceso se crea un Thread simple que ejecuta el programa de forma secuencial. Ese Thread puede crear threads adicionales y dichos threads ejecutan el mismo programa en el mismo proceso. pero cada thread puede estar ejecutando una parte diferente de programa en cualquier momento dado.

Hay que tomar en cuenta algunas cosas en los Threads:

  • Existen con el proceso y utilizan los recursos del proceso.
  • Tienen su propio flujo independiente de control durante el tiempo que el proceso dueño del thread exista.
  • Duplica solamente los recursos esenciales necesarios para ser independientemente planificable.
  • Puede compartir recursos del proceso con otros Threads que tambien actuan de manera independiente o dependiente.
  • El thread es terminado si el proceso dueño del Thread muere.
  • Es ligero debido a que la mayoria del consumo se ha conseguido mediantre la creacion de su proceso.

Los Threads con el mismo proceso comparten recursos debido a las siguientes caracteristicas:

  • Los cambios realizados por un Thread a un recurso compartido pueden ser visto por todos los demas threads.
  • Dos punteros como el mismo valor apuntan a los mismos datos.
  • La lectura y escritura hacia la misma direccion de memoria es posible y se necesita de forma explicita que el programador realice la sincronizacion.

Creacion de Threads.

Inicialmente el main() comprende un unico thread por defecto, los demas threads deberan ser creados por el programador. Cada threads es identificado por un thread ID, cuando nos referimos a threads ID en C o C++ utilizaremos el tipo ppthread_t.

A su creacion cada Thread debera ejecutar una funcion Thread. Esta es una funcion ordinaria y contiene el codigo que el Thread deberia ejecutar. Cuando la funcion retorne el thread terminara. En GNU/Linux las funciones threads toman un simple parametro de tipo void*, y se tiene un valor de retorno de tipo void*.

La funcion encargada de crear un nuevo thread es la funcion pthread_create

Código
  1. int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

donde:

pthread_t *thread es un unico identificador para el nuevo thread devuelto por la subrutina
const pthread_attr_t *attr es un puntero a un objeto de atributos para threads. Este objeto controlara detalles sobre como el thread interactuara con el resto del programa. Si se pasa NULL como atributo para el thread, el thread sera creado con los atributos por defectos.

void*(*start_routine)(void*) es un puntero a la funcion del thread, la cual es un puntero a una funcion del tipo void* (*) void(*).

void *arg es un argumento para el thread del tipo void*, lo que sea que pases sera pasado como argumento a la funcion del thread cuando el thread empiece a ejecutarse.

Una llamada a pthread_create retorna el control al thread principal inmediatamente para que este continue su ejecucion, mientras tanto el nuevo thread inicia su ejecucion. Linux planifica ambos threads de forma asincronica por lo tanto no se tiene un control de cual thread ira avanzando mas rapido que el otro por lo tanto para trabajar se necesitara una sincronizacion que veremos mas adelante.

Veamos un pequeño ejemplo pero primero debemos tomar algo en cuenta; Se  debe enlazar la libreria pthread al programa cada vez que se utilizen threads, esto lo realizaremos añadiendo '-lpthread' al momento de enlazar.

Código
  1. #include <pthread.h>
  2. #include <stdio.h>
  3.  
  4. void* MundoThread(void *ptr)
  5. {
  6.  int j=0;
  7.  for(j;j<10;j++)printf("Mundo\n");
  8. }
  9.  
  10. int main()
  11. {
  12.  int i=0;
  13.  pthread_t thread_id; //Con esto crearemos una variable para obtener el thread_id
  14.  pthread_create(&thread_id,NULL,&MundoThread,NULL);//Creamos el Thread
  15.  for(i;i<10;i++)printf("Hola ");
  16.  return 0;
  17. }
  18.  

Pasando Datos al Thread.

Pasar datos a traves del argumento nos da una manera sencilla de proveer al thread de los datos que necesita para realizar una correcta ejecucion. Como se pudieron dar cuenta la variable que recibe los argumentos es de tipo void* por lo cual no se podria pasar una gran cantidad de datos directamente a traves del argumento, por lo tanto utilizaremos el argumento del thread para pasar un puntero a una estructura o a una cadena de caracteres. Es recomendable y comunmente utilizado el crear una estructura para cada thread que se quiera ejecutar la cual contenga los datos que dicho thread necesitara.

Código
  1. #include <pthread.h>
  2. #include <stdio.h>
  3.  
  4. struct thread_arg
  5. {
  6.  int ini;
  7.  int fin;
  8.  int par;
  9. };
  10.  
  11. void* Count(void* argument)
  12. {
  13.   struct thread_arg* arg = (struct thread_arg*) argument;
  14.   for(arg->ini;arg->ini<=arg->fin;arg->ini++)
  15.   {
  16.     if(arg->par==1)
  17.     {
  18.       if(arg->ini%2==0)printf("%d \n",arg->ini);
  19.     }
  20.     else
  21.     {
  22.       if(arg->ini%2==1)printf("%d \n",arg->ini);
  23.     }
  24.   }
  25. }
  26.  
  27. int main()
  28. {
  29.  pthread_t thread_id1, thread_id2;
  30.  struct thread_arg thread1;
  31.  struct thread_arg thread2;
  32.  int junk;
  33.  thread1.ini=0;
  34.  thread1.fin=10000;
  35.  thread1.par=1;
  36.  
  37.  thread2=thread1;
  38.  thread2.par=0;
  39.  
  40.  pthread_create(&thread_id1,NULL, &Count,&thread1);
  41.  pthread_create(&thread_id2,NULL, &Count,&thread2);
  42.  return 0;
  43. }

Si se fijan este codigo deberia de funcionar, pero no muestra nada en pantalla. Esto se debe a que cuando el proceso termina los threads terminan sin importar si completaron o no su funcion. Para este caso pasaremos al proximo tema.

Esperando Threads

En el codigo anterior vimos que aunque deberia de funcionar no muestra nada en pantalla debido a que el proceso termina antes de que estos lleguen a ejecutarse. Una solucion a esto es forzar el Thread principal (main()) a esperar a que los demas Threads terminen. Para estos casos tenemos la funcion pthread_join()

Código
  1. int pthread_join(pthread_t thread, void **value_ptr);

pthread_t thread es el thread por el cual esperaremos.

void **value_ptr es un puntero a una variable tipo void* que recibira el valor de retorno del thread. En caso de que no se quiera saber el valor de retorno del thread se puede pasar el valor NULL al segundo parametro.

Ahora veremos el ejemplo pasado de una forma que mostrara la salida de los threads por pantalla y luego terminara el proceso.


Código
  1. #include <pthread.h>
  2. #include <stdio.h>
  3.  
  4. struct thread_arg
  5. {
  6.  int ini;
  7.  int fin;
  8.  int par;
  9. };
  10.  
  11. void* Count(void* argument)
  12. {
  13.   struct thread_arg* arg = (struct thread_arg*) argument;
  14.   for(arg->ini;arg->ini<=arg->fin;arg->ini++)
  15.   {
  16.     if(arg->par==1)
  17.     {
  18.       if(arg->ini%2==0)printf("%d \n",arg->ini);
  19.     }
  20.     else
  21.     {
  22.       if(arg->ini%2==1)printf("%d \n",arg->ini);
  23.     }
  24.   }
  25. }
  26.  
  27. int main()
  28. {
  29.  pthread_t thread_id1, thread_id2;
  30.  struct thread_arg thread1;
  31.  struct thread_arg thread2;
  32.  int junk;
  33.  thread1.ini=0;
  34.  thread1.fin=10000;
  35.  thread1.par=1;
  36.  
  37.  thread2=thread1;
  38.  thread2.par=0;
  39.  
  40.  pthread_create(&thread_id1,NULL, &Count,&thread1);
  41.  pthread_create(&thread_id2,NULL, &Count,&thread2);
  42.  pthread_join(thread_id1,NULL);
  43.  pthread_join(thread_id2,NULL);
  44.  
  45.  return 0;
  46. }

Valor de Retorno en un Thread

En caso de que el segundo argumento no sea NULL estamos requiriendo que nos sean devuelto los valores de retorno. Este valor de retorno sera colocado en la direccion pasada como argumento. Hay que tomar en cuenta que el valor de retorno es como el argumento en pthread_create(), es de tipo void*.

Código
  1. #include <pthread.h>
  2. #include <stdio.h>
  3.  
  4. void* Euler(void *ptr)
  5. {
  6.  int j=0;
  7.  int a=0;
  8.  int b=*((int*)ptr);
  9.  for(j;j<=b;j++)a+=j;
  10.  return (void*)a;
  11. }
  12.  
  13. int main()
  14. {
  15.  int i=0, num;
  16.  pthread_t thread_id;
  17.  scanf("%i",&num);
  18.  pthread_create(&thread_id,NULL,&Euler,&num);
  19.  pthread_join(thread_id,(void*)&i);
  20.  printf("El numero %d de la escalera es: %d\n",num,i);
  21.  return 0;
  22. }
  23.  

Atributos en Threads

Los Atributos en los Threads nos dan la posibilidad de optimizar el funcionamiento de un thread en especifico. La funcion pthread_create acepta  como segundo parametro un puntero a un objeto de atributos de thread. En caso de que se pase NULL el thread se iniciara con los atributos por defecto. Para modificar los atributos de un thread simplemente hay que realizar algunos pasos.

1) Creamos una variable del tipo pthread_attr_t.
2) Llamamos la funcion pthread_attr_init() pasando como parametro la direccion de memoria de la variable del tipo. pthread_attr_t.
3) Modificamos el objeto que contiene los atributos para contener los atributos decididos.
4) Pasamos a pthread_create() la direccion de memoria del objeto con los atributos en el segundo parametro.
5) Llamamos pthread_attr_destroy() para liberar el objeto de los atributos.

Para modificar los objetos existen unas funciones especificas pthread_attr_ las cuales los invitare a que lean sobre el tema debido a que posiblemente a muchos no les   sirva de mucho darle importancia sobre los atributos a los threads

http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setaffinity_np.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setdetachstate.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setguardsize.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setinheritsched.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setschedparam.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setschedpolicy.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setscope.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setstack.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setstackaddr.3.html
http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_attr_setstacksize.3.html

Sincronizacion  y Zonas Criticas.

Cuando programamos utilizando threads debemos tener un especial cuidado debido a que no sabemos como el S.O. ha planificado la ejecucion, por lo tanto un thread puede detenerse para dar paso a otro inmediatamente inicie su ejecucion como puede durar una gran cantidad de tiempo.

La causa mas probable de fallo cuando se trabaja con threads es que varios threads quieran utilizar el mismo recurso a la vez. Por ejemplo pensemos en un programa que tiene dos Threads realizando una lista de tareas hasta que la terminen todas. Llega el caso de que ambos procesos terminen sus respectivas tareas y quede solo una; El primer thread llega y toma la tarea, pero antes de marcarla como que la tomo debido a la planificacion del S.O. dicho thread se pausa y entra en funcionamiento el segundo thread. Aqui hay un problema debido a que tendremos varios threads realizando una tarea que se supone que deberia realizarse una sola vez. Para estos casos surgieron los Mutex, esto daba la posibilidad de que solo un thread a la vez pudiese acceder a la lista y mientras ese thread estuviese utilizandola el otro thread no tendria acceso hasta que el thread que accedio primero al recurso tome lo que necesite.

Mutex

El Sistema Operativo nos da la posibilidad de utilizar Mutex como una forma de sincronizacion para evitar el tipo de problema explicado en el caso anterior. como su nombre lo expresa, un Mutex (Mutual Exclusion Locks) como su nombre lo indica son cerraduras especiales las cuales un thread a la vez puede cerrar. Cuando un thread bloquea un mutex y luego otro thread trata de bloquearlo, el segundo thread se queda en espera o es bloqueado, con esto el Sistema Operativo evita que ocurra que dos threads a la vez bloqueen el mismo Mutex y accedan a los mismos recursos.

Para crear un mutex crearemos una variable del tipo pthread_mutex_t y pasaremos un puntero a la funcion pthread_mutex_init() como primer parametro, el segundo parametro sera un puntero a un objeto de atributos de un mutex el cual especificara los aatributos del mutex. Si el segundo parametro es NULL el mutex iniciara con los atributos por defecto. Una variable para un mutex puede ser inicializada una y solo una vez. por cierto existe una forma mas facil de inicializar un mutex y es asignandole el valor especial PTHREAD_MUTEX_INITIALIZER.

Código
  1. int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

mas info: http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_init.html

Un thread puede tratar de bloquear un Mutex llamando la funcion pthread_mutex_lock() en el. En caso de que el Mutex este desbloqueado la funcion bloqueara el Mutex y retornara inmediatamente, pero si esta bloqueado paralizara la ejecucion y retornara cuando el Mutex sea liberado por el otro thread. En caso de que varios threads traten de bloquear un thread ya bloqueado, la ejecucion de todos cesara y cuando el thread que bloqueo el Mutex libere otro Thread lo bloqueara sin un orden predecible especifico. La funcion pthread_mutex_unlock() desbloquea el Mutex y deberia ser llamada por el thread que bloqueo el Mutex.

Código
  1. int pthread_mutex_lock(pthread_mutex_t *mutex);
  2. int pthread_mutex_trylock(pthread_mutex_t *mutex);
  3. int pthread_mutex_unlock(pthread_mutex_t *mutex);

mas info:http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_lock.html

Código
  1. #include <pthread.h>
  2. #include <stdio.h>
  3.  
  4. pthread_mutex_t mutex[4];
  5. int var[4]={0,0,0,0};
  6. pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
  7.  
  8. void *Mult(void *arg)
  9. {
  10. int k = *((int*)arg);
  11. pthread_mutex_lock(&mutex[k]);
  12. k++;
  13. k*=250;
  14. int j = k-249;
  15. pthread_mutex_unlock(&lock);
  16. for(j;j<=k;j++)
  17. {
  18. if(j%3==0||j%5==0)var[(k/250)-1]+=j;
  19. }
  20. pthread_mutex_unlock(&mutex[(k/250)-1]);
  21. }
  22.  
  23. int main()
  24. {
  25. int i;
  26. pthread_t threadid[4];
  27. for(i=0;i<4;i++)
  28. {
  29. pthread_mutex_init(&mutex[i],NULL);
  30. pthread_mutex_lock(&lock);
  31. pthread_create(&threadid[i],NULL,&Mult,&i);
  32. pthread_mutex_lock(&lock);
  33. pthread_mutex_unlock(&lock);
  34. }
  35. for(i=0;i<4;i++)pthread_mutex_lock(&mutex[i]);
  36. printf("resultado: %i\n",var[0]+var[1]+var[2]+var[3]);
  37. return 0;
  38. }

Semaphores

Los Semaphores al igual que los Mutex son mecanismos para la sincronizacion de threads. Un semaphore es un contador que puede ser utilizado para sincronizar multiples threads, para que multiples threads puedan acceder al mismo recurso (dependiendo de la cantidad de threads admitidos para trabajar a la vez con un recurso).

Un Semaphore es representado por una variable del tipo sem_t y antes de utilizarlos deben de ser inicializados de forma semejante a los mutex, con la funcion sem_init() cuyo primer parametro es un puntero a una variable del tipoo sem_t, el segundo parametro deberia ser cero y el tercer parametro sera el valor inicial del semaphore. Si en algun momento necesitamos saber cual es el valor del Semafore podemos conseguirlos utilizando la funcion sem_getvalue() la cual recibe como primer parametro un puntero a una variable del tipo sem_t inicializada y como segundo parametro un puntero a una variable tipo int para obtener el valor de retorno. En caso de que no se necesite un semaphore es bueno destruirlo con sem_destroy() el cual recibe un puntero a un semaphore.

Código
  1. int sem_init(sem_t *sem, int pshared, unsigned int value);
mas info:[urlhttp://opengroup.org/onlinepubs/007908799/xsh/sem_init.html[/url]

Código
  1. int sem_getvalue(sem_t *sem, int *sval);
mas info:http://opengroup.org/onlinepubs/007908799/xsh/sem_getvalue.html

Código
  1. int sem_destroy(sem_t *sem);
mas info: http://opengroup.org/onlinepubs/007908799/xsh/sem_destroy.html


Cada Semaphore es un contador de enteros positivos y soportan basicamente dos operaciones.

wait: Disminuye el valor del Semaphore en 1, Si el valor del semaphore a la hora de realizar la operacion wait es cero, la funcion queda bloqueada hasta que el valor del semaphore sea positivo. La funcion especifica para realizar un wait en un semaphore es sem_wait() para un wait bloqueante y sem_trywait() para un wait no bloqueante. Ambas funciones reciben como parametro un puntero a una variable del tipo sem_t

post: Incrementa el valor del Semaphore en 1, Si el Semaphore previamente estaba en cero y otro thread estaba bloqueado esperando para realizar un wait en el semaphore, este al realizarse el post se desbloqueara y ejecutara el wait sobre el semaphore. La funcion para realizar un post es sem_post() y al igual que sem_wait() y sem_trywait() recibe un puntero a una variable del tipo sem_t.

Código
  1. int sem_wait(sem_t *sem);
  2. int sem_trywait(sem_t *sem);
mas info:http://opengroup.org/onlinepubs/007908799/xsh/sem_wait.html

Código
  1. int sem_post(sem_t *sem);
mas info:http://opengroup.org/onlinepubs/007908799/xsh/sem_post.html

En el ejemplo supongamos que tenemos una piramide de numeros y quisieramos obtener obtener la mayor posible suma de la piramide siguiendo un camino. La piramide esta organizada de la siguiente forma:
Código:
1
8 3
5 6 8

Código
  1. #include <pthread.h>
  2. #include <semaphore.h>
  3. #include <stdio.h>
  4.  
  5. int piramid[3][3]={{1,0,0},{8,3,0},{5,6,8}};
  6. pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
  7. sem_t sem1, sem21, sem22, sem31, sem32, sem33, semmaster;
  8.  
  9. void* Sum(void* argument)
  10. {
  11. int var=0;
  12. sem_wait(&sem1);
  13. pthread_mutex_unlock(&mutex);
  14. var+=piramid[0][0];
  15. if(sem_trywait(&sem21)!=-1)
  16. {
  17. var+=piramid[1][0];
  18. if(sem_trywait(&sem31)!=-1)
  19. {
  20. var+=piramid[2][0];
  21. sem_post(&semmaster);
  22. return (void*)var;
  23. }
  24. else if(sem_trywait(&sem32)!=-1)
  25. {
  26. var+=piramid[2][1];
  27. sem_post(&semmaster);
  28. return (void*)var;
  29. }
  30. }
  31. else if(sem_trywait(&sem22)!=-1)
  32. {
  33. var+=piramid[1][1];
  34. if(sem_trywait(&sem32)!=-1)
  35. {
  36. var+=piramid[2][1];
  37. sem_post(&semmaster);
  38. return (void*)var;
  39. }
  40. else if(sem_trywait(&sem33)!=-1)
  41. {
  42. var+=piramid[2][2];
  43. sem_post(&semmaster);
  44. return (void*)var;
  45. }
  46. }
  47.  
  48. }
  49.  
  50. int main()
  51. {
  52.  pthread_t thread_id[4];
  53.  int i,res=0,sem=0;
  54.  sem_init(&sem1,0,4);
  55.  sem_init(&sem21,0,2);
  56.  sem_init(&sem22,0,2);
  57.  sem_init(&sem32,0,2);
  58.  sem_init(&sem31,0,1);//Este trabajaria como si fuera un Mutex
  59.  sem_init(&sem33,0,1);//Al igual que este
  60.  sem_init(&semmaster,0,0);
  61.  
  62.  for(i=0;i<4;i++)
  63.  {
  64.  pthread_mutex_lock(&mutex);
  65.  pthread_create(&thread_id[i],NULL, &Sum,NULL);
  66.  }
  67.  while(sem!=4)sem_getvalue(&semmaster,&sem);
  68.  for(i=0;i<4;i++)
  69.  {
  70.  pthread_join(thread_id[i],(void*)&sem);
  71.  if(sem>res)res=sem;
  72.  }
  73.  printf("La mayor suma de la piramide es %i\n",res);
  74.  return 0;
  75. }
  76.  
10  Programación / Programación C/C++ / [Capitulo II] Procesos en: 6 Octubre 2010, 08:19 am
Procesos

   Un programa en ejecucion recibe el nombre de proceso. Estos estan gestionados por el sistema operativo. Un proceso esta conformado por las instrucciones que van a ser ejecutadas por el microprocesador, el estado de ejecucion en un momento especifico, la memoria de trabajo para el proceso y otra informacion que requiera el sistema operativo.

   En los sistemas operativos basados en Linux cada proceso es identificado por un unico ID llamado Process ID(pid). Los Process IDs son numeros de 32bits asignados secuencialmente por Linux cada vez que un nuevo proceso es creado. Aparte de todo esto, cada proceso tiene un proceso padre, exceptuando el proceso 'init', cuando nos refiramos desde un proceso hijo hacia un proceso padre nos referiremos con la abreviatura ppid(Parent Process ID).

   Para referirnos al ID de un proceso utilizaremos el tipo 'pid_t' el cual esta definido en el archivo cabecera '<sys/types.h>'. Una pequeña aclaracion, el tipo de dato pid_t es simplemente un tipo 'signed int', utilizar el tipo 'pid_t' o 'signed int' no hara ningun cambio pero para facilidad de lectura de tu codigo por otras personas es preferible utilizar 'pid_t' cuando te refieras a un Process ID.

Obteniendo nuestro Process ID


   En algunos casos necesitaremos obtener nuestro Process ID, para verificarlo en una lista, para pasarlo a otro proceso, etc. Para obtener dicho Process ID se nos ha dotado de dos funciones getpid(),para obtener nuestro propio Process ID, y getppid(),para obtener el Process ID del proceso padre, dichas funciones se encuentran en el archivo cabecera 'unistd.h' el cual es el archivo que nos da acceso a las API del Sistema Operativo POSIX (Portable Operative System Interface for uniX).
   
   Ninguna de las funciones vistas anteriormente reciben un parametro y como valor de retorno devuelven un pid_t, el cual dependera de la funcion que ha sido llamada.

Código:
pid_t getpid (void)
pid_t getppid (void)


   Veamos un pequeño ejemplo del uso de estas funciones:

Código
  1. #include <sys/types.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4.  
  5. int main()
  6. {
  7. pid_t currentpid, parentpid;
  8. currentpid = getpid();
  9. parentpid = getppid();
  10. printf("El proceso %i es padre del proceso %i \n",parentpid,currentpid);
  11. return 0;
  12. }
  13.  

Como vemos si ejecutamos varias veces el mismo programa en la misma consola, el valor del Process ID del proceso padre no varia debido a que la consola es el proceso padre.

Creando un Proceso.

Existen dos tecnicas comunes para crear un proceso, la primera es utilizando 'system()', es sencilla de utilizar pero esta se debe de utilizar con cierta precaucion debido a que es ineficiente y es considerada como un riesgo de seguridad.La segunda es utilizando fork() o exec(), esta es mas compleja pero nos otorga flexibilidad, velocidad y seguridad.

Utilizando system():


Código:
int system (const char *string)

Hay que tomar en consideracion 2 valores de retorno, devolvera '127' si la ejecucion en la consola falla, en caso de otro error el valor de retorno sera -1. Aparte de estos valores, system() mostrara en pantalla en caso de ser posible el proceso o comando ejecutado.

Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. printf("%i \n",system("dir"));
  6. return 0;
  7. }

para mas informacion:
Código:
man 3 system

Utilizando fork() y exec():


Código:
pid_t fork(void)

La funcion fork() crea un proceso hijo identico al proceso padre, la unica diferencia entre ellos es el PID y la direccion de memoria fisica en la RAM. En los actuales Sistemas Operativos las direcciones de las variables en memoria no corresponden a la verdadera memoria fisica en hardware. Las direcciones estan administradas por direcciones virtuales en el Sistema Operativo por esta razon en el proceso padre y el proceso hijo incluso cuando tienen la misma direccion virtual de memoria, la direccion fisica es diferente.

La funcion fork() devuelve en el proceso padre el pid del proceso hijo, mientras que en el proceso hijo devuelve 0.

Código
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4.  
  5. int main()
  6. {
  7. pid_t proc;
  8. int status,value=0;
  9.  
  10. if(proc=fork())
  11. {
  12. printf("Process: %i %x\n",getpid(),&value);
  13. waitpid(proc,&status,0);
  14. printf("%i \n",value);
  15. return 0;
  16. }
  17.  
  18. else
  19. {
  20. printf("Process: %i %i %x\n",getpid(),getppid(),&value);
  21. value = 2000;
  22. return 0;
  23. }
  24. }

para mas informacion:
Código:
man 2 fork


La familia exec()


Código:
int execl(const char *path, const char *arg, ...)
int execlp(const char *file, const char *arg, ...)
int execle(const char *path, const char *arg, ..., char * const envp[])
int execv(const char *path, char *const argv[])
int execvp(const char *file, char *const argv[])

Las funciones exec() remplazan el programa en ejecucion por otro programa dentro de un proceso. Inmediatamente se hace una llamada exec() el proceso en ejecucion se detiene y el nuevo programa inicia la ejecucion asumiendo que la llamada no tenga un error. Debido a que exec() remplaza el programa actual en ejecucion, este no retornara el control a menos que suceda un error o nuevo programa en ejecucion termine.

Veamos un pequeño ejemplo para utilizar fork() y exec() en el mismo programa:

Código
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7. pid_t proc;
  8. int status,value=0;
  9.  
  10. if(proc=fork())
  11. {
  12. waitpid(proc,&status,0);
  13. printf("Clear Used \n");
  14. return 0;
  15. }
  16.  
  17. else
  18. {
  19. execvp("clear",argv);
  20. return 0;
  21. }
  22. }

Terminando un proceso


   Normalmente un proceso termina de dos formas. o llamando una funcion de salida, o por el valor de retorno. Cada proceso tiene un valor de salida. Cada proceso tiene un codigo de salida y ese codigo es devuelto a su proceso padre, entiendase por codigo el valor de retorno.

   En algunos casos necesitaremos cerrar un proceso, debido a que ya no lo necesitemos, para estos casos existe la funcion kill(). La funcion kill recibe 2 parametros. El primer parametro es el PID de un proceso o de un grupo de procesos. El segundo parametro es la señal, la cual es un valor constante.

Código
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <signal.h>
  5.  
  6. int main(int argc, char *argv[])
  7. {
  8. pid_t proc;
  9. int status,value=0;
  10.  
  11. if(proc=fork())
  12. {
  13. kill(proc,SIGTERM);
  14. if(status==0)printf("El proceso %i se ha cerrado \n",proc);
  15. return 0;
  16. }
  17.  
  18. else
  19. {
  20. while(1)printf("KILL ME. \n");
  21. }
  22. }

para mas informacion sobre kill():
Código:
man 2 kill

para mas informacion sobre el valor constante de las señales:
Código:
/usr/include/bits/signum.h

Esperando la terminacion de un proceso


   Debido a que el S.O. Linux es un sistema operativo multitareas cuando trabajamos con varios procesos, por ejemplo con una llamada a fork, no existe la certeza de cual proceso terminara primero. En algunas ocasiones necesitaremos esperar el valor de retorno de un proceso hijo o de multiples procesos hijos que habran realizado diferentes instrucciones y para estos casos existe la funcion wait().

Código
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7. pid_t proc;
  8. int status,value=0;
  9.  
  10. if(proc=fork())
  11. {
  12. waitpid(proc,&status,0);
  13. if(status==0)printf("El proceso %i ha terminado con exito \n",proc);
  14. return 0;
  15. }
  16.  
  17. else
  18. {
  19. return 0;
  20. }
  21. }

para mas informacion:
Código:
man 2 wait
Páginas: [1] 2 3
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines