Tubos, dup2 y exec ()

Tengo que escribir un shell que puede ejecutar tuberías. Por ejemplo, comandos como ls -l | wc -l ls -l | wc -l “. He analizado correctamente el comando dado por el usuario como se muestra a continuación:

“ls” = firstcmd

“-l” = frsarg

“wc” = scmd

“-l” = secarg

Ahora tengo que usar dos tenedores ya que los comandos son dos y una tubería. El bloque de código que escribí para ejecutar el comando es el siguiente:

 pid_t pid; int fd[2]; pipe(fd); pid = fork(); if(pid==0) { dup2(fd[WRITE_END], STDOUT_FILENO); close(fd[READ_END]); execlp(firstcmd, firstcmd, frsarg, (char*) NULL); } else { pid=fork(); if(pid==0) { dup2(fd[READ_END], STDIN_FILENO); close(fd[WRITE_END]); execlp(scmd, scmd, secarg, (char*) NULL); } } 

Entonces cuando ejecuto mi shell y entro en el comando ls -l | wc -l ls -l | wc -l (por ejemplo) el resultado de los ejecutivos no se muestra pero el shell sigue ejecutándose normalmente.

Lo extraño es que el resultado del comando solo se muestra cuando finalizo mi shell con “exit” o “^ C”.

¿Qué está mal con esa salida? ¿Por qué no aparece justo después de ingresar el comando?

Debe cerrar todos los descriptores de canalización tanto en el proceso principal como en el proceso secundario (después de la duplicación en el proceso secundario). En su código, el problema principal es que el proceso de wc no finaliza porque todavía hay escritores presentes (ya que el proceso principal no ha cerrado el final de escritura). Los cambios se muestran a continuación. También agregué el waitpid en el proceso padre para esperar el proceso wc .

 pid_t pid; int fd[2]; pipe(fd); pid = fork(); if(pid==0) { dup2(fd[WRITE_END], STDOUT_FILENO); close(fd[READ_END]); close(fd[WRITE_END]); execlp(firstcmd, firstcmd, frsarg, (char*) NULL); fprintf(stderr, "Failed to execute '%s'\n", firstcmd); exit(1); } else { pid=fork(); if(pid==0) { dup2(fd[READ_END], STDIN_FILENO); close(fd[WRITE_END]); close(fd[READ_END]); execlp(scmd, scmd, secarg,(char*) NULL); fprintf(stderr, "Failed to execute '%s'\n", scmd); exit(1); } else { int status; close(fd[READ_END]); close(fd[WRITE_END]); waitpid(pid, &status, 0); } } 

Hmm, lo suficientemente cerca. Se olvida de manejar cerca de algún descriptor de archivo después de la bifurcación.

Aquí hay alguna referencia:

  1. Acerca de pipe, http://unixwiz.net/techtips/remap-pipe-fds.html
  2. Acerca del descriptor de archivos, http://www.usna.edu/Users/cs/aviv/classes/ic221/s14/lec/09/lec.html

Aquí está mi código:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  using namespace std; #define INPUT_END 1 #define OUTPUT_END 0 int main(int argc, char* argv[]) { pid_t pid; int fd[2]; pipe(fd); pid = fork(); if(pid==0) { close(fd[INPUT_END]); dup2(fd[OUTPUT_END], STDIN_FILENO); close(fd[OUTPUT_END]); execlp("wc", "wc", "-l",(char*) NULL); } else { pid=fork(); if(pid==0) { close(fd[OUTPUT_END]); dup2(fd[INPUT_END], STDOUT_FILENO); close(fd[INPUT_END]); execlp("ls","ls","-l",(char*) NULL); } close(fd[OUTPUT_END]); close(fd[INPUT_END]); } }