Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closing pipe file descriptor in C

Tags:

c

pipe

Here is the code:

int main() {

    int fd[2];
    pipe(fd);
    int r = fork();
    if (r > 0) { //parent
        close(fd[0]);
        // do a bunch of things
    } else { //child
        close(fd[1]);
        // do a bunch of things
    return 0;
}

This is a piece of code where the parent writes to the pipe and child reads from the pipe. My question is: for the two close statements, what exactly are they closing? The parent and the child should share the same file, i.e. fd[0] and fd[1]. If fd[0] is closed in the parent, shouldn't it also be closed in child?

like image 272
Xufeng Avatar asked Feb 26 '14 04:02

Xufeng


People also ask

Do you need to close pipe C?

Since descriptors are shared between the parent and child, we should always be sure to close the end of pipe we aren't concerned with. On a technical note, the EOF will never be returned if the unnecessary ends of the pipe are not explicitly closed.

Does close Send EOF?

Until every FD referring to the write end of a pipe is closed, it won't return EOF.

How do I close a file descriptor?

close() closes a file descriptor, so that it no longer refers to any file and may be reused.

Why do we close pipe in C?

If you close fd[0] in parent and also in child there is from nowhere you can read from the pipe, in the reverse case if you close fd[1] in both the processes you cannot write into pipe, So we close the read descriptor in one process so that the process can only write and the other process will close write descriptor ...


2 Answers

From http://linux.die.net/man/2/pipe pipe() creates a pipe which consists of two file descriptors which correspond with the two "ends" of the pipe, the read end and the write end. It's not really the same thing as a file. The kernel is reading data from the write end, buffering it for you, and transferring it it to the read end.

This should make it obvious why pipe() creates two file descriptors. The writer writes all the data it needs into the write fd and closes the fd. This also triggers an EOF to be sent. The reader would usually keep reading data until it encounters the EOF and closes its end. In this scenario, there's a period of time where the write fd is closed but data is still buffered in the pipe, waiting to be read out by the reader. It doesn't make sense to have a single fd, as you'll need another layer of coordination between the writer and reader processes, otherwise who will do the closing, and when?

like image 196
congusbongus Avatar answered Sep 30 '22 06:09

congusbongus


The pipe() call always returns an integer array where the first element of array is the read descriptor to read from pipe and second element is the write descriptor to write into the pipe. The pipes provide one way communication. If you close fd[0] in parent and also in child there is from nowhere you can read from the pipe, in the reverse case if you close fd[1] in both the processes you cannot write into pipe, So we close the read descriptor in one process so that the process can only write and the other process will close write descriptor which will enable the process to only read from pipe.

like image 40
prince Avatar answered Sep 30 '22 08:09

prince