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 for ls -l

    and another process for sort

    ? 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

      

+3


source to share


2 answers


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.

+1


source


Yes, you need to call fork at least twice, once for each program in the pipeline. Remember that exec replaces the program image of the current process, so your shell ceases to exist the moment you start sorting or (tr).



0


source







All Articles