How do I chain stdout in one child process to stdin in another child in C?

后端 未结 1 1328
慢半拍i
慢半拍i 2020-12-17 03:17

I\'ve been messing around in C trying to figure out how to do this. Let\'s say I have my main program, the parent process. The parent creates three child processes, each of

相关标签:
1条回答
  • 2020-12-17 03:55

    So you have a loop that creates several child processes. Each of these child processes will be using two pipes: read from previous and write to the next. To set up a pipe for the reading end you need to close the write end of the pipe, and dup2 the read end into the stdin. Similar for the pipe where the process will be writing.

    void set_read(int* lpipe)
    {
        dup2(lpipe[0], STDIN_FILENO);
        close(lpipe[0]); // we have a copy already, so close it
        close(lpipe[1]); // not using this end
    }
      
    void set_write(int* rpipe)
    {
        dup2(rpipe[1], STDOUT_FILENO);
        close(rpipe[0]); // not using this end
        close(rpipe[1]); // we have a copy already, so close it
    }
    

    When you fork each children you need to attach the pipes to it.

    void fork_and_chain(int* lpipe, int* rpipe)
    {
        if(!fork())
        {
            if(lpipe) // there's a pipe from the previous process
                set_read(lpipe);
            // else you may want to redirect input from somewhere else for the start
            if(rpipe) // there's a pipe to the next process
                set_write(rpipe);
            // else you may want to redirect out to somewhere else for the end
    
            // blah do your stuff
            // and make sure the child process terminates in here
            // so it won't continue running the chaining code
        }
    }
    

    With this in hand you can now write a loop that continuously forks, attaches the pipes, and then reuses the output pipe as the input pipe for the next one. Of course, once both ends of a pipe have been connected to child processes, the parent should not leave it open for itself.

    // This assumes there are at least two processes to be chained :)
    
    // two pipes: one from the previous in the chain, one to the next in the chain
    int lpipe[2], rpipe[2];
    
    // create the first output pipe
    pipe(rpipe);
    
    // first child takes input from somewhere else
    fork_and_chain(NULL, rpipe);
    
    // output pipe becomes input for the next process.
    lpipe[0] = rpipe[0];
    lpipe[1] = rpipe[1];
    
    // chain all but the first and last children
    for(i = 1; i < N - 1; i++)
    {
        pipe(rpipe); // make the next output pipe
        fork_and_chain(lpipe, rpipe);
        close(lpipe[0]); // both ends are attached, close them on parent
        close(lpipe[1]);
        lpipe[0] = rpipe[0]; // output pipe becomes input pipe
        lpipe[1] = rpipe[1];
    }
    
    // fork the last one, its output goes somewhere else      
    fork_and_chain(lpipe, NULL);
    close(lpipe[0]);
    close(lpipe[1]);
    

    The closing bits are very important! When you fork with an open pipe, there will be four open file descriptors: two on the parent process, and two others on the child process. You have to close all of those you won't be using. That's why the code above always closes the irrelevant ends of the pipes in the child processes, and both ends on the parent.

    Also note that I am giving special treatment to the first and the last processes, because I don't know where the input for the chain will come from, and where the output will go to.

    0 讨论(0)
提交回复
热议问题