2011-02-23 24 views
5

Tengo que escribir el programa que crea el proceso usando pipe().fork(), pipe() y exec() proceso de creación y comunicación

Mi primera tarea es escribir un proceso principal que genere cuatro procesos secundarios usando la función fork().

Una vez que el fork() tiene éxito, reemplace el proceso secundario con otro proceso rover1, rover2, rover3, and rover4, aunque todos ellos tienen el mismo código.

La función de los procesos es la siguiente.

  1. Cada proceso secundario recibe inicialmente su propio número. Recibe un nuevo número del padre. Usando la siguiente fórmula crea su propio nuevo número de la siguiente y lo envía al padre:

    mynumber = (3 * mynumber + 4 * numberreceived)/7

  2. Este proceso continúa hasta que el padre envía el mensaje de que el sistema es estable. El padre también tiene su número inicial. Recibe los números de todos los niños y calcula su nuevo número de la siguiente manera:

    mynumber = (3 * mynumber + numbers sent by all the children)/7

  3. El padre enviará este número para todos sus hijos. Este proceso continuará hasta que el padre descubra que su número ya no cambia. En ese momento le dirá a los niños que el sistema se ha estabilizado.

Esto es lo que hice, pero mi profesor dijo que tengo que usar exec() para ejecutar el elemento secundario y reemplazar el proceso secundario con otro proceso hijo. No estoy seguro de cómo usar exec(). Podrías ayudarme con esto por favor.

Adjunto solo la primera generación de mi hijo.

// I included stdio.h, unistd.h stdlib.h and errno.h 
int main(void) 
{ 
    // Values returned from the four fork() calls 
    pid_t rover1, rover2, rover3, rover4; 

    int parentnumber, mynumber1, mynumber2, mynumber3, mynumber4; 

    int childownnumber1 = 0, status = 1, childownnumber2 = 0, 
     childownnumber3 = 0, childownnumber4 = 0, numberreceived = 0; 

    printf("Enter parent number: "); 
    printf("%d", parentnumber); 
    printf("Enter each children number"); 
    printf("%d %d %d %d", mynumber1, mynumber2, mynumber3, mynumber4); 

    // Create pipes for communication between child and parent 
    int p1[2], p2[2]; 
    // Attempt to open pipe 
    if (pipe(p1) == -1) { 
    perror("pipe call error"); 
    exit(1); 
    } 
    // Attempt to open pipe 
    if (pipe(p2) == -1) { 
    perror("pipe call error"); 
    exit(1); 
    } 

    // Parent process generates 4 child processes 
    rover1 = fork(); 

    // if fork() returns 0, we're in the child process; 
    // call exec() for each child to replace itself with another process 
    if (rover1 == 0) { 
    for(; numberreceived != 1;) { 
     close(p1[1]); // Close write end of pipe 
     close(p2[0]); // Close read end of second pipe 

     // Read parent's number from pipe 
     read(p1[0], &numberreceived, sizeof(int)); 

     if (numberreceived == 1) { 
     // System stable, end child process 
     close(p1[0]); 
     close(p2[1]); 
     _exit(0); // End child process 
     } 

     mynumber1 = (int)((3*mynumber1 + 4*numberreceived)/7.0); 

     printf("\nrover1 number: "); 
     printf("%i", mynumber1); 

     // Write to pipe 
     write(p2[1], &mynumber1, sizeof(int));  
    }  
    } 
    /* Error: 
    * If fork() returns a negative number, an error happened; 
    * output error message 
    */ 
    if (rover1 < 0) { 
    fprintf(stderr, 
      "can't fork, child process 1 not created, error %d\n", 
      errno); 
    exit(EXIT_FAILURE); 
    } 
} 
+0

¿La funcionalidad de lo que se supone que los procesos hijos deben hacer está contenida dentro de los ejecutables 'roverX'? – user470379

+0

@ user470379- Sí, supongo. – cool

Respuesta

2

El exec familia de funciones se utiliza para reemplazar el proceso actual con un nuevo proceso. Tenga en cuenta el uso de la palabra reemplazar. Una vez que se llama al ejecutivo, el proceso actual desaparece y comienza el nuevo proceso. Si desea crear un proceso separado, primero debe fork, y luego exec el nuevo binario dentro del proceso hijo.

Usar las funciones exec es similar a ejecutar un programa desde la línea de comando. El programa a ejecutar así como los argumentos pasados ​​al programa se proporcionan en la llamada a la función exec.

Por ejemplo, el siguiente comando exec* es el equivalente al comando posterior shell:

execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);

/bin/ls -r -t -l

* Tenga en cuenta que "arg0" es el nombre del comando/archivo ejecutar


Dado que esto es tarea, es importante comprender bien este proceso. Puede comenzar leyendo la documentación en pipe, fork y exec combinados con algunos tutoriales para comprender mejor cada paso.

Los siguientes enlaces deberían ayudar a empezar:

+0

@ jschmier- Gracias por todos esos enlaces. Utilizaré la función exec como arriba. – cool

1

Si se supone que el uso exec, entonces usted debe dividir el programa en dos binarios

Básicamente, el código que ahora ejecuta el niño debe estar en el segundo binario y debe invocarse con exec.

Antes de llamar a una de las exec familias de funciones, también deberá redirigir los descriptores de tubería a la entrada/salida estándar del nuevo proceso usando dup2. De esta forma, el código en el segundo binario que obtiene exec 'd no tendrá conocimiento de la tubería y solo leerá/escribirá en la entrada/salida estándar.

También vale la pena señalar que algunos de los datos que está utilizando ahora en el proceso hijo se heredan de los padres a través del fork. Al usar exec, el niño no compartirá los datos ni el código del padre, por lo que quizás también pueda considerar transmitir los datos necesarios a través de la tubería.

+0

Haré eso ahora mismo. – cool

Cuestiones relacionadas