2010-04-17 15 views
8

Estoy tratando de implementar un shell de linux que admita tuberías. Ya he hecho comandos simples, comandos que se ejecutan en segundo plano, redirecciones, pero aún falta la tubería.Implementación de tubería

Ya he leído sobre él y he visto algunos fragmentos de código, pero todavía no he podido resolver una solución funcional.

Lo que tengo hasta ahora:

int fd[2]; 

pipe(fd); 

pid_t pid = fork(); 

if (pid == -1) 
    return -1; 

if (pid == 0) 
{ 
    close(fd[1]); //close write to pipe, in child 
    execlp("cat", "cat", "names.txt", NULL); 
} 

else 
{ 
    close(fd[0]); //close read from pipe, in parent 
    execlp("sort", "sort", NULL); 
} 

Soy un programador novato, ya que seguramente se puede decir, y cuando estoy programando algo que no saben mucho sobre, siendo este el caso, evidentemente, yo gustaría comenzar con algo realmente fácil y concreto y luego construir a partir de ahí.

Entonces, antes de poder implementar tres y más comandos diferentes en la canalización, me gustaría poder calcular "ls names.txt | sort" o algo similar, en el que names.txt es un archivo de nombres alfabéticamente desordenado

Código actualizado, pero todavía no funciona.

Gracias.

Respuesta

9

Es necesario sustituir uno el stdout del niño con el extremo de escritura del tubo y el stdin del otro niño con el extremo de lectura:

if (pid == 0) 
{ 
    close(fd[1]); //close write to pipe, in child 
    dup2(fd[0], STDIN_FILENO); // Replace stdin with the read end of the pipe 
    close(fd[0]); // Don't need another copy of the pipe read end hanging about 
    execlp("cat", "cat", "names.txt", NULL); 
} 
else 
{ 
    close(fd[0]); //close read from pipe, in parent 
    dup2(fd[1], STDOUT_FILENO); // Replace stdout with the write end of the pipe 
    close(fd[1]); // Don't need another copy of the pipe write end hanging about 
    execlp("sort", "sort", NULL); 
} 
4

Mire en la llamada a la biblioteca estándar pipe(). Esto se usa para crear una tubería. Por supuesto, debe hacer parte del trabajo antes delfork(), para que el proceso hijo herede correctamente el descriptor del archivo.

También tenga en cuenta el orden de los argumentos a dup2():

int dup2(int oldfd, int newfd); 

dup2() hace newfd ser la copia de oldfd, cerrando newfd primero si es necesario

+0

Yo ya lo sabía, simplemente olvidé agregar la declaración de pipa al código. ¿Qué sugieres ahora? Gracias. – nunos

+0

Pensé que dup2 (0, fd [0]) estaba copiando lo que se suponía que iba a stdout a fd [0], que es la entrada del proceso. Supongo que eso es lo que quiero, ¿verdad? – nunos

+0

@nunos: dup2() no realiza la copia, copia * descriptores de archivo *. Como fd [0] es el fd de un extremo de tu tubería recién creada, no tiene mucho sentido cerrarlo, como lo hará dup2(). – unwind