Take the 2-minute tour ×

I'm trying to understand the usage of pipe.

A parent process will pipe and if the parent forks, the child process will inherit the pipe. So now we hae a direct link to the child process and they can communicate?

I get lost when we start to close pipes and redirect pipes. Does anyone have a good explanation on closing pipes and redirecting pipes?

Thank you in-advance.

share|improve this question

5 Answers 5

up vote 6 down vote accepted

Here's the deal.

  1. A pipe is a software abstraction, that has two ends, each one a fd. Whatever you write on at one end (write fd), you can read off the other end (read fd).
  2. The trick in using a pipe is that you switch the stdin of some process with the read fd of the pipe. Now, you can write to the write fd of the pipe, and when the other process reads what he thinks is his stdin, he actually reads the read fd of the pipe (and gets your data).
  3. For two way communication, you can get another pipe, and switch the stdout of the process with the write fd of the pipe. Now, whatever the process writes to its stdout, you can read off the read fd of the pipe.

Here is what it looks like:

P1=[WR FD]===========[RD FD]=[STDIN]=P2
P1=[RD FD]===========[WR FD]=[STDOUT]=P2

P1 and P2 are processes. And "===" depict the pipes.

Your question was specifically about closing and redirecting. That comes into play when you perform the switch I referred to earlier. Let's say you have obtained a pipe by using the pipe() system call.

int fd[2];

Now you create a child process, and in that process perform the switch, like so:

if (!fork()) // 0 return value indicates that you are in the child process
    dup2(fd[0], 0); // dup2 first closes 0 in the child process, then duplicates
                    // fd[0] as 0; keep in mind that 0 is stdin and fd[0] is the
                    // read end of the pipe

    exec(something); // start the new process, which when it reads stdin, will be
                     // reading the pipe instead
share|improve this answer

See Pipeline.

Simple example

ls -l | less

In this example, ls is the Unix directory lister, and less is an interactive text pager with searching capabilities. The pipeline lets the user scroll up and down a directory listing that may not fit on the screen.

Creating pipelines programmatically



alt text

share|improve this answer

You use the dup family of system calls to change a new file descriptor to one of the first three system calls.

int new_stdout = open("filename", O_WRONLY);
/* ... error check ... */
if (!fork()) {
    /* in child */
    dup2(new_stdout, 1);
    execve("program", argv, envp);

This makes "filename" write its standard out to "filename".

share|improve this answer

The child process inherits the parent's open descriptors. Default ones are stdin, stdout, stderr. They do not provide a means for the child to communicate directly with the parent since they actually go to the console. So typically you close or redirect those so you don't pollute the parent's console I/O.

But if you have a pair of pipes open you can use their descriptors as inherited by the child to communicate both ways between the two processes. Use one descriptor per direction.

share|improve this answer

We often use a pipe. As says Amardeep, the child process inherits the parent's descriptor, including pipe.

Here is an example for 2 commands. I'm not sure of my algorithm for n commands :-)

void do__pipe(char** cmd1, char** cmd2)
    int fd[2]; /* fd[0] for reading fd[1] for writting */

    if (pipe(fd) == -1)

    switch (fork())
       case -1:
      perror("fork"); exit (1);
       case 0:
      close (fd[0]);
      dup2 (fd[1], STDOUT_FILENO);
      close (fd[1]);
      execvp (cmd1[0], cmd1);
      exit (1);


    switch (fork())
       case -1:
      perror("fork (2)"); exit (1);
       case 0:
      close (fd[1]);
      dup2 (fd[0], STDIN_FILENO);
      close (fd[0]);
      execvp (cmd2[0], cmd2);
      exit (1);


this code has been taken from a small shell I had to write for my studies, so char** cmd1 would be something like ["cat", "/etc/passwd"] and cmd2 could be ["wc", "-l"]

share|improve this answer

Your Answer


