Pipe and process control
I am working on a tiny shell (tsh) implemented in C (that's the assignment). One part of the job belongs to PIPING. I need to pipe the output of a command to another command. eg:ls -l | sort
When I start the shell, every command I execute on it is handled by the child process that it spawns. After the child has finished, the result is returned. For pipelines, I first wanted to implement a coded example to test how it works. I wrote a method that partially works. Problems come when I run the pipe command, after the child process finishes, the whole program exits with it! Obviously I am handling the child process signal incorrectly (method code is below).
My question is:
-
How does process control work with pipe ()? if i run the command
ls -l | sort
it creates a child process forls -l
and another process forsort
? From the pipe examples I've seen so far, only one process (fork ()) is created. -
When the second command (
sort
from our example) is processed, how can I get its process ID?
EDIT: I get the result twice while running this code. don't know why it works twice, there is no loop.
Here is my code:
pid_t pipeIt(void){
pid_t pid;
int pipefd[2];
if(pipe(pipefd)){
unix_error("pipe");
return -1;
}
if((pid = fork()) <0){
unix_error("fork");
return -1;
}
if(pid == 0){
close(pipefd[0]);
dup2(pipefd[1],1);
close(pipefd[1]);
if(execl("/bin/ls", "ls", (char *)NULL) < 0){
unix_error("/bin/ls");
return -1;
}// End of if command wasn't successful
}// End of pid == 0
else{
close(pipefd[1]);
dup2(pipefd[0],0);
close(pipefd[0]);
if(execl("/usr/bin/tr", "tr", "e", "f", (char *)NULL) < 0){
unix_error("/usr/bin/tr");
return -1;
}
}
return pid;
}// End of pipeIt
source to share
Yes, the shell must use fork to execute each subprocess. Remember that when you call one of the function families execve()
, it replaces the current process image with exec'ed. Your shell cannot continue processing further commands if it is executing a subprocess directly, because after that it no longer exists (except as a subprocess).
To fix this, just fork()
go back to the branch pid == 0
and run the command ls
on that child. Remember wait()
for both (all) child processes, unless you mean the pipeline should run asynchronously.
source to share