Reputation: 33
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
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:
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
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