X
X
xozzslip2017-01-28 16:37:14
C++ / C#
xozzslip, 2017-01-28 16:37:14

How do pipes work in UNIX?

The man page on channels gives the following example of using channels:

main(int argc, char *argv[])
       {
           int pipefd[2];
           pid_t cpid;
           char buf;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <string>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           if (pipe(pipefd) == -1) {
               perror("pipe");
               exit(EXIT_FAILURE);
           }

           cpid = fork();
           if (cpid == -1) {
               perror("fork");
               exit(EXIT_FAILURE);
           }

           if (cpid == 0) {    /* Child reads from pipe */
               close(pipefd[1]);          /* Close unused write end */

               while (read(pipefd[0], &buf, 1) > 0)
                   write(STDOUT_FILENO, &buf, 1);

               write(STDOUT_FILENO, "\n", 1);
               close(pipefd[0]);
               _exit(EXIT_SUCCESS);

           } else {            /* Parent writes argv[1] to pipe */
               close(pipefd[0]);          /* Close unused read end */
               write(pipefd[1], argv[1], strlen(argv[1]));
               close(pipefd[1]);          /* Reader will see EOF */
               wait(NULL);                /* Wait for child */
               exit(EXIT_SUCCESS);
           }
       }

I can't understand why you can be sure that the parent will write something to the channel first, and only then the child will try to read something. Could there be a situation in which the child tries to read data from the channel before something appears there?
And in general, how to make the process wake up only when there is something to read in the channel? So that he read everything that is and fell asleep back? How does it work at the OS level?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vladimir Dubrovin, 2017-01-29
@xozzslip

You are using a blocking read/write, so the read operation will wait until data is available. For the duration of the blocking, the process will fall asleep, nothing else needs to be done for this. If the writing process writes a sufficiently large amount of data and the reading process does not have time to read the data, then the pipe's buffer will be overflowed, then the write operation will be blocked and the writing process will "sleep".
Now, if you want to avoid blocking, then you need to switch descriptors to non-blocking mode and use select () / poll () or analogues.
At the OS level, pipe() is simply a memory buffer into which data can be written to and read from via a descriptor.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question