Archivos para fork

fork fork fork, 2ª parte

Publicado en informatica bizarra con etiquetas , , , , el Abril 17, 2008 por Pumpkin Dreamer

Creo que es un buen momento para exponer el codigo que prometi de como hacer una malla de procesos. El problema consiste en crear una malla o arbol de procesos de NxN teniendo en cuenta que los hijos siempre moriran antes que sus padres.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
 int pid, i=1, j=1, aux, x, y, k, fila, columna;

 if(argc!=3) printf("Error en el numero de argumentos.\n");
 else
 {
  x=atoi(argv[1]);
  y=atoi(argv[2]);
  fila=0;
  columna=0;
  int hijos[y], primera_fila[x];

  for(i=0; i<x; i++)
  {
   pid=fork(); //primer fork
   primera_fila[i]=pid;
   if(pid==0) //codigo de los hijos del proceso malla
   {
    fila=i+1;
    columna=1;
    i=x+1; //hacemos que el proceso hijo salga del for a la fuerza
    hijos[0]=getpid();
   }
  }

  if(fila!=0 && columna!=0) //cuando no nos encontremos en el proceso malla
  {
   for(j=2; j<=y; j++) //fabricaremos con otro for el resto de hijos
   {
    pid=fork();
    if(pid==0) //en caso de ser un hijo
    {
     columna=j;
     hijos[j-1]=getpid();
    }
    else j=y+1; //si no es un hijo forzamos la salida
   }
  }

  if(fila==0 && columna==0) //en caso de ser la malla
  {
   printf("Soy el proceso malla: mi pid es %d\n", getpid());
   printf("Soy el proceso malla: mi pid es %d: mis hijos de la primera fila son:");
   for(i=0; i<x; i++)
   {
    if(i==x-1) printf(" %d\n", primera_fila[i]);
    else printf(" %d,",primera_fila[i]);
   }
   for(k=0; k<x; k++) wait(0); //esperara hasta que se muera el ultimo hijo
   printf("Soy malla (%d) y muero.\n", getpid());
  }
  else //si no estamos en la malla
  {
   printf("Soy el proceso %d%d: mi pid es %d. Mis padres son: ", fila, columna, getpid());
   for(i=columna-1; i>=0; i--)
   {
    if(i==0) printf(" %d\n", hijos[i]);
    else printf(" %d,",hijos[i]);
   }
   if(columna!=y) wait(0); //si no es el ultimo hijo dejamos al proceso en espera
   else sleep(20); //si es el ultimo hijo lo dormimos antes de que muera para poder ejecutar pstree -c -p -l o similar

   printf("Soy el %d%d (%d) y muero.\n", fila, columna, getpid());
   exit(0); //el hijo muere y despues su padre, y asi sucesivamente hasta que muera la malla
  }
 }
}

fork fork fork

Publicado en informatica bizarra con etiquetas el Marzo 3, 2008 por Pumpkin Dreamer

Todo proceso (programa en ejecucion) puede crear mediante una bonita instruccion llamada fork() una copia de si mismo, es decir, una replica llamada proceso hijo. Cada proceso tiene a su vez un numero de identificacion llamado PID y tambien el numero identificador del proceso padre que lo genero llamado PPID, estos se puede obtener con las funciones getpid() y getppid()… ¿Hasta aqui sencillo, no?

Bien, compliquemos un poquillo mas las cosas con las posibilidades que esto nos brinda. Por un lado podremos montar las llamadas mallas de procesos y por otro (no intenteis esto en casa) virus cojoneros que acabarian con cualquier windows con solo 3 lineas de codigo, pero que como no, cualquier linux podria resistir sin demasiadas dificultades gracias a su kernel.

1. Mallas de procesos
Las mallas de procesos estan formadas por un proceso padre del que descenderan X hijos (entiendase X como la anchura del arbol) y a su vez cada uno de estos X hijos tendra hasta Y hijos (entiendase Y como la altura del arbol).

Las mallas de procesos tiene posibilidades enormes a la hora de gestionar sistemas operativos y controlarlos gracias a su capacidad de auto-replicacion… ¿Pero como demonios los gestionamos? El truco esta en comparar los PID del proceso de turno con el de su padre gracias al retorno de la instrucciones fork(), asi saber donde nos encontramos y obrar en consecuencia.

fork() –> devuelve el PID del proceso
salida: -1 –> ocurrio un error mientras intentabamos crear el proceso hijo
salida: 0 –> estamos en el proceso hijo
salida: cualquier otro PID –> estamos en el proceso padre


Cuando termine de preparar mi malla seguramente exponga el codigo, hasta entonces seguire toqueteando todo este asunto del fork y demas llamadas al sistema.

2. La bomba fork
Y ahora vamos a una aplicacion maliciosa pero interesante, asi que ya sabeis chicos, no intenteis esto en casa.

La bomba fork se fundamenta en la capacidad de crear procesos hijos y en que los recursos de un sistema NO son infinitos, estos pequeños bichitos pueden llegar a dejarnos basicamente sin recursos. El objetivo es replicar un proceso estupido (o al que le hemos incluido ordenes y llamadas al sistema para que haga algo mas) hasta que la lista de procesos se satura y la memoria se agota poco a poco.

Por ejemplo (en C):

#include <unistd.h>

 int main()
 {
   while(0==0)
     fork();
 }

Y asi tendriamos un programa que en cuestion de tiempo llenaria la cola de procesos del planificador y agotaria la memoria provocando que tengamos que reiniciar.

¿Alguna manera de librarnos de este wabbit?
Por supuesto que hay una manera: reiniciar y limitar el numero de procesos que pueden haber en la cola de procesos.
En windows es algo mas engorroso, ya que tendriamos que toquetear opciones que ahora mismo no sabria ni por donde empezar. Sin embargo en Linux no tendremos que preocuparnos por nada, ya que en el kernel hay una opcion llamada RLIMIT_NPROC configurada ya de antemano con el numero maximo de procesos que pueden haber en la cola, despues solamente tendriamos que enviar una señal kill -9 PID_del_wabbit mediante la consola, borrar el wabbit y listo.