Apodeus
Apodeus

Reputation: 33

When and why do I have to close pipe?

I'm trying to understand pipes, and am working on an example:


#define _XOPEN_SOURCE 700

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    pid_t p;
    int status;
    int pipefd[2];
    pipe(pipefd);
    p = fork();

    if(p == 0)
    {
        dup2(pipefd[1], 1);
        close(pipefd[0]);
        close(pipefd[1]);

        execlp(argv[1], argv[1], NULL); 
        perror(argv[1]);

        exit(1);
    }

    dup2(pipefd[0], 0);
    close(pipefd[0]);
    close(pipefd[1]);

    execvp(argv[2], argv + 2);
    perror(argv[2]);

    return 0;
}

I don't understand why this code closes the pipefd before using it.

Why do we call close here?

Upvotes: 3

Views: 7899

Answers (2)

davmac
davmac

Reputation: 20671

dup2(pipefd[1], 1);
close(pipefd[0]);
close(pipefd[1]);

This duplicates the file descriptor for the write end of the pipe to file descriptor #1, which corresponds to stdout - to which a programs normal output will go. It then closes the original file descriptors for both ends of the pipe, however:

  • the write end of the pipe itself will not be closed, because another open file descriptor (1) now refers to it
  • the process has forked, and the child similarly duplicates the read end of the pipe before closing its own pipe file descriptors. That means the read end of the pipe is also being held open, in the child process.

It is not the case that we necessarily have to close the original pipe file descriptor of the pipe. However, it is usually good practice to close file descriptors that we don't need, and that's what this program does. Multiple file descriptors can refer to the same pipe (or file, or other entity), and the pipe/file/whatever itself is not closed until all the file descriptors that refer to it are closed.

Also, it's worth noting that the read end of the pipe will only see an "end of file" condition (i.e. have read return 0) if the write end of the pipe is closed (meaning that all open file descriptors which refer to it are closed).

Upvotes: 7

Some programmer dude
Some programmer dude

Reputation: 409472

You already duplicate the descriptor with the dup2 call, so the pipefd[1] descriptor isn't needed anymore in the child process. Similarly in the parent process.

In fact, descriptors are a limited resource, if you keep the pipe descriptors open then there are two less available descriptors for the process.

Upvotes: 3

Related Questions