lunes, 10 de diciembre de 2012

Árboles de procesos con fork [ C ]

Saludos a todos, espero y aun me recuerden, estoy de regreso después de una larga ausencia, el motivo: tratar de explicar como crear un árbol de procesos en C como se te antoje, ¡SI! escuchaste bien como se te antoje, que tenga el número de hijos que tu quieras. Esta publicación nace gracias al Profe. de Sistemas Operativos que trató de intimidarnos en la clase pasada (OkNo jeje no intimidar pero si espantar, ok eso tampoco solo nos dio una probadita de lo que podría venir) bueno eso sentí yo, estamos estudiando los procesos como se crean, matan, etc. y como examen nos pondrá a hacer un árbol de procesos a como se le antoje, aunque nos proporcionará un código base, nunca me gusta sobrevivir de cosas que no son producto de mis experimentos, prácticas, etc.


Recordemos que la programación es en C y bajo alguna distribución de GNU/Linux y el objetivo del post no es aprender a compilar o cosas así. Sería necesario que ya cuentes con algunos conocimientos previos. Disculpen la sencillez y brevedad de la publicación pero tengo reducido mi tiempo para dar todas esas explicaciones.

Si lo que necesitas es saber que cosa es exactamente "fork()" te recomiendo visites la siguiente liga que te aseguro tiene mucha información de utilidad, blog de un colega (Espero y no se enoje por usar su blog como fuente jeje) Curso de Programación en C para GNU/Linux (V) .

A continuación muestro algunos puntos que yo tomé en cuenta que podrían suceder, checa la figura que muestro a continuación (de pruebas que ya fueron realizadas) y analiza el código:

Ejemplo 1

Fig. 1 Muestra un papá con 3 hijos.



Se declara pid, mas adelante si te das cuenta tenemos un ciclo que va a dar 3 "vueltas", dentro del ciclo se crearan 3 hijos con el método fork (la parte del else juega un papel importante), el método exit() en pocas palabras te ayudara a que no le salgan mas  hijos al hijo actual de esta manera el papá siempre sera el mismo.

Ejemplo 2

Fig. 2 Muestra un papá con 3 hijos y cada hijo a su vez tuvo 2 hijos.



La nueva implementación es un ciclo for después del metodo sleep... el método exit se encuentra al final del ciclo for (si se coloca en otra parte ten por hecho que afectara el funcionamiento del programa), si miras con mas cuidado te percatarás que es lo mismo del ejemplo anterior pero dentro del else, el segundo for (el que trabaja con y) controla cuantos nietos deseas que tenga el padre por cada hijo (espiritú santo, amen! jejee OkNo).

Ejemplo 3

Fig. 3 Muestra a un papá con 3 hijos de los cuales solo el primero le dio 2 nietos.



Ahora, que pasa si debemos limitar el número de nietos que tendrá el padre por cada hijo, fácil utilizamos un if. En este ejemplo solo el primer hijo tendrá sus propios 2 hijos. Para saber cuando estoy trabajando con el hijo "1" el valor de la variable x en el ciclo for será 1, por lo cual con una condición pudo implementar la parte del ciclo 2 que vimos en el ejemplo anterior dentro de un if que detecte cuando se trabaja con el primer hijo que a su vez se encentrara dentro del primero ciclo. 

Compañero programador tu trabajo es tratar de hacer árboles mas grandes, prácticamente es repetir estos códigos en varias ocasiones, lo que si es importante es saber donde colocarlos jeje.

Bueno hasta aquí espero y estos ejemplos les sean útiles, estoy consciente que es un tema difícil de trabajar y mas cuando uno mismo es un aprendiz pero espero aportar algo interesante a su conocimiento, me despido: ¡Hasta la próxima!.

P.D. Te amo Yani :D

    Choose :
  • OR
  • To comment
22 comentarios:
Write comentarios
  1. Disculpe como podria hacer un cadigo para un árbol asi:
    o (estos son procesos)
    |
    o
    |
    o
    / | \
    / | \
    / | \
    o o o
    /||\ /\ |
    o oo o o o o
    | | | |
    o o o o
    GRACIAS!!!

    ResponderEliminar
    Respuestas
    1. Hola, por el momento se me hace dificil hacer el código con el contenido de tu comentario, si me pueden mandar al correo un dibujo del diagrama, tal vez sí te pueda ayudar.

      Eliminar
  2. hola la verdad no entiendo bien sobre procesos y tengo una practica sobre crear un proceso padre que contenga un hijo y que cada uno imprima los numeros del 1-100 podrian ayudarme?

    ResponderEliminar
    Respuestas
    1. Hola, disculpa que no te pueda ayudar :( yo tampoco se como realizar eso.

      Eliminar
    2. Esto podría servirte aunque son números aleatorios
      /*Jesús Antonio Tepec Hernández*/

      #include
      #include
      #include
      #include
      #include
      int main(int argc, char **argv)
      {
      int pid; /* identificador del proceso */
      int numero,cantidad,contador;
      int hora = time(NULL);

      srand(hora);//semeilla
      cantidad=100;//se define el número de elementos ha ser procesados aleatoriamente

      pid = fork();
      if ( pid < 0 )
      {
      printf("¡¡ No se pudo duplicar !!\n");
      exit(1);
      }
      if ( pid == 0 )
      {
      /* Proceso hijo */
      printf("Elementos del proceso hijo: \n\n");
      for(contador = 0; contador<cantidad; contador++)
      {
      numero = rand()%100;
      printf("%d ", numero);
      }
      }
      else
      {
      /* Proceso padre */
      printf("\nElementos del proceso padre: \n\n");
      for(contador = 0; contador<cantidad; contador++)
      {
      numero = rand()%100;
      printf("%d ", numero);
      }
      printf("\n\n");
      }
      getch();
      }

      Eliminar
  3. como se podria hacer con recursividad para q por cada padre tenga dos hijos y la altura del arbol sea parametrica?

    ResponderEliminar
  4. Hola de nuevo, fíjate que estoy tratando de hacer que para todos los procesos(el padre y los hijos) su pid sea parte de una lista enlazada, así que implementé una lista enlazada, pero resulta que al recorrer la lista en los nodos se ha guardado solo el pid del padre. hicé algo así:

    pid_t pid;
    int x;
    for(x=1; x<=3; x++){
    pid=fork();
    if(pid){
    printf("Soy el proceso %d\n",getpid());
    tmp= (struct kool_list *)malloc(sizeof(struct kool_list));
    tmp->pid=getpid();
    list_add(&(tmp->list), &(mylist.list));
    sleep(2);
    }
    else{
    printf("soy el hijo %d, mi padre es %d\n",getpid(),getppid());
    tmp= (struct kool_list *)malloc(sizeof(struct kool_list));
    tmp->pid=getpid();
    list_add(&(tmp->list), &(mylist.list));
    sleep(2);
    exit(0);
    }
    }

    Como verás, en tu codigo tan solo puse funciones para agregar nodos a una lista enlazada, se supone que cuando se trata de un proceso hijo, debería también guardar si pid, pero esto es la sálida:

    Soy el proceso 2722
    soy el hijo 2723, mi padre es 2722
    Soy el proceso 2722
    soy el hijo 2724, mi padre es 2722
    Soy el proceso 2722
    soy el hijo 2725, mi padre es 2722



    traversing the list using list_for_each()
    pid= 2722
    pid= 2722
    pid= 2722

    Como ves, en mi lista tan solo quedaron 3 nodos, todos con el pid del padre, cuando lo que me gustaría hacer es que al recorrer la lista quedará algo así:

    traversing the list using list_for_each()
    pid= 2722
    pid= 2723
    pid= 2724
    pid= 2725

    Tienes alguna idea del porque no esta funcionado?

    ResponderEliminar
  5. Hola, logré solucionar el problema:
    for(x=1; x<=3; x++){
    pid=fork();
    if(pid){
    printf("Soy el proceso %d\n",getpid());
    tmp= (struct kool_list *)malloc(sizeof(struct kool_list));
    tmp->pid=pid;
    tmp->ppid=getppid();
    list_add(&(tmp->list), &(mylist.list));
    sleep(2);
    }
    else{
    printf("soy el hijo %d, mi padre es %d\n",getpid(),getppid());
    sleep(2);
    exit(0);
    }
    }

    printf("\n \n \n");

    Arroja la siguiente salida:

    Soy el proceso 9487
    soy el hijo 9488, mi padre es 9487
    Soy el proceso 9487
    soy el hijo 9489, mi padre es 9487
    Soy el proceso 9487
    soy el hijo 9490, mi padre es 9487



    traversing the list using list_for_each()
    pid= 9490, ppid= 9416
    pid= 9489, ppid= 9416
    pid= 9488, ppid= 9416


    Solo por si alguien en el futuro le sirve.

    Saludos!!

    ResponderEliminar
  6. OLA! :D
    Alguien me podria ayudar a hacer un proceso con esta forma:
    O
    / | \
    O O O
    | | |
    O O O
    | | |
    O O O

    ResponderEliminar
    Respuestas
    1. Hola, en base a los ejemplos de arriba puedas crear tu árbol, solo es cuestión de que leas con cuidado.

      Eliminar
  7. Perdona cuál es tu correo para mandarte un código a ver si puedes ayudarme

    ResponderEliminar
  8. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  9. Hola. alguien podría detallarme que hace el método "exit()". No cortaría la ejecución del for ?

    ResponderEliminar
    Respuestas
    1. Exit es el método que mata al proceso.

      Eliminar
  10. Perdona, tu código es muy correcto en cuanto a la formación de la estructura pero no hay ni un wait en los padres esperando la terminación del proceso hijo, osea que dejas que el proceso init termine con todos los hijos zombies que haya, y eso no es muy correcto.

    ResponderEliminar
  11. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  12. Hola, intento compilar tu programa pero me da un error en cuanto al exit(0). lab7.c:67:4: warning: incompatible implicit declaration of built-in function ‘exit’
    Que podria ser? y como lo podria solucionar?

    ResponderEliminar
  13. Oie papu muy rica su aportasion me a serbido de mucho suerte con Llani

    ResponderEliminar
  14. hola a que se refiere un if(fork())y if(!fork())?
    a que si es hijo o si es padre?... :(
    quiero ir creando el arbol en dibijo con el codigo pero me pierdo ya que cada proceso inicia nuevamente el codigo ayuda porfa :::
    fork()
    if(fork())
    if(!fork())
    fork()
    fork()

    ResponderEliminar
  15. Hola , tengo duda en el comando sleep() ¿como afecta a la creación de procesos? , que hace por que si los quito todos los procesos se crean de un solo y mismo padre. Gracias.

    ResponderEliminar