tuberias syscall son read que programacion por pipes los libreria example comunicacion bidireccionales c process pipe

syscall - Tuberías y procesos



read pipe c (3)

En primer lugar, está llamando también a wait from the child processes [edit: no, no lo está, ya que cada hijo llama a execvp].

Además, wait no toma un puntero al pid del niño, sino a una variable donde se escribirá el estado del proceso (lo que significa que está tirando el pid de su hijo).

Finalmente, intente usar waitpid con la opción "WNOHANG". No se bloqueará, puede poner ambos en un bucle mientras hace otras cosas, y puede verificar si los procesos secundarios han salido inspeccionando las variables de estado. man waitpid .

Premisa: escriba un programa para consultar al usuario sobre dos cadenas de entrada. Cada cadena de entrada debe ser un comando Unix, con argumentos permitidos. Por ejemplo, la entrada 1 podría ser ls -l y la entrada 2 podría ser more . El programa creará una tubería y dos procesos secundarios. El primer proceso secundario ejecutará el comando especificado en la primera entrada. Saldrá a la tubería en lugar de la salida estándar. El segundo proceso secundario ejecutará el comando especificado en la segunda entrada. Tomará su entrada de la tubería en lugar de la entrada estándar. El proceso principal esperará a que completen sus dos hijos, y luego todo se repetirá. La ejecución se detendrá cuando se ingrese el símbolo ''@'' como primer comando. Aquí está el código que tengo:

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main(){ /* Program Termination Symbol */ const char terminate = ''@''; /* String delimiter */ const char delimiter = '' ''; /* Pipe file ID''s */ int fileID[2]; /* Parent ID''s */ int pid1, pid2; /* String token */ char * token, * token2; /* User input */ char * user_input, line[100]; user_input = (char *) malloc(100); /* Unix Commands */ char * command1[10], *command2[10]; for (int i=0; i<10; i++) { command1[i] = (char *)malloc(100*sizeof(char)); command2[i] = (char *)malloc(100*sizeof(char)); } /* Begin main program logic */ printf("Please enter the first command: /n"); user_input = gets(line); while (user_input[0] != terminate) { token = (char *) malloc(100*sizeof(char)); for (int i=0; i<10; i++) { if (i == 0) { token = strtok(user_input, &delimiter); } else { token = strtok(NULL, &delimiter); } if (token != NULL) { strcpy(command1[i], token); } else { command1[i] = 0; } } printf("Please enter the second command: /n"); user_input = gets(line); token2 = (char *) malloc(100*sizeof(char)); for (int i=0; i<10; i++) { if (i == 0) { token2 = strtok(user_input, &delimiter); } else { token2 = strtok(NULL, &delimiter); } if (token2 != NULL) { strcpy(command2[i], token2); } else { command2[i] = 0; } } /* Pipe and execute user commands */ /* Create pipe */ pipe(fileID); /* Create child processes */ pid1 = fork(); if (pid1 != 0) { pid2 = fork(); } /* First child process */ if (pid1 == 0) { dup2(fileID[1], 1); execvp(command1[0], command1); } /* Second child process */ if (pid2 == 0) { dup2(fileID[0], 0); execvp(command2[0], command2); } /* Wait for children to terminate */ wait(&pid1); wait(&pid2); /* Repeat */ printf("Please enter the first command: /n"); user_input = gets(line); } return 0; }

El problema con el que me estoy encontrando es con mi espera. Si tengo ambas cosas, lo cual tendría sentido para mí (una espera por niño), entonces el programa se congela después de ejecutar la primera tubería. Si elimino la segunda espera, el programa comenzará de nuevo su ciclo, pero no aceptará la entrada del teclado que no sea enter, y producirá una segfault. Entonces, con ambas esperas, la entrada y la salida es ...

Please enter the first command: ls Please enter the second command: more Pipe Pipe.c Pipe.c~

... y luego se bloquea. Si elimino la segunda espera, la entrada / salida es ...

Please enter the first command: ls Please enter the second command: more Pipe Pipe.c Pipe.c~ Please enter the first command: (I hit enter, nothing else will work) Segmentation fault

¿Alguien tiene alguna sugerencia? Está claramente relacionado con esperar en los dos procesos, pero no sé cómo manejarlo.

Este programa ahora es 100% funcional. ¡Muchas gracias por su ayuda, a todos! El desbordamiento de la pila ha sido uno de los mejores recursos en Internet. Muchas gracias a todos por tomarse el tiempo para revisar mi código y darme sus sugerencias.


Estoy de acuerdo con todo lo que dijo torak, pero para resolver su problema, debe cerrar sus tuberías. Creo que estás "colgando" porque la tubería todavía está abierta.

Entonces en el padre, justo antes de "esperar", cerraría las tuberías.

close(fileID[0]); close(fileID[1]); wait(&pid_status); wait(&pid_status);

Luego, justo antes de cada ejecución, cerraría los extremos de la tubería que el niño no usará:

close(fileID[0]); dup2(fileID[1], 1); execvp(command1[0], command1); close(fileID[1]); dup2(fileID[0], 0); execvp(command2[0], command2);

Eso debería resolver tu ahorcamiento. Además de las sugerencias hechas por torak, también recomendaría fgets en lugar de evitar un desbordamiento de búfer.


Un par de cosas. No estoy seguro de que sean la causa de sus problemas, pero aún hay cosas que considerar antes de enviar su tarea.

  1. No creo que estés usando la wait correctamente. Según http://linux.die.net/man/2/wait , no toma el puntero pid como argumento.

  2. Cada vez que token2 el ciclo, llama a malloc para token y token2 , pero no veo una versión correspondiente de la memoria.

  3. Has escrito una sola función monolítica. Una buena práctica de codificación sugeriría dividirlo en una colección de subrutinas

  4. Finalmente, y posiblemente relacionado con el punto 3, las siguientes dos líneas de código aparecen dos veces en su código. De nuevo, no es un error, sino una duplicación innecesaria y poco elegante.

    printf ("Por favor ingrese el primer comando: / n"); user_input = gets (línea);