Let's be accurate regarding the file descriptors and bear in mind that during fork and execvp file descriptors are inherited by child processes unless marked as w/ CLOEXEC flag. Check the man pages:
fork(2):
The child inherits copies of the parent's set of open file descriptors. Each file descriptor in the child refers to the same open file description (see open(2)) as the corresponding file descriptor in the parent.
open(2):
By default, the new file descriptor is set to remain open across an execve(2) (i.e., the FD_CLOEXEC file descriptor flag described in fcntl(2) is initially disabled); the O_CLOEXEC flag, described below, can be used to change this default. The file offset is set to the beginning of the file (see lseek(2)).
But this behaviour, I supposed, exactly what you were relying on by calling fork after pipe...
No other words, lets' draw this:
stdin, stdout
/
/
/
/
/ R; W;
/
Child - - Parent
stdin/out, R(del),W stdin/out, R(fd_backup), W(del)
/
/
/
/
/ R1; W1;
/
Child - - Parent
stdin/out, R(fd_backup), stdin, stdout
R1(del), W1 R(fd_backup - old);
R1(fd_backup - new); W1(del)
/
/
/
/R2; W2;
/
/
Child - - Parent
stdin, stdout, stdin, stdout
R(fd_backup - old), R (fd_backup - old),
R1(fd_backup - new), R1 (fd_backup - new),
R2(del),W2 R2 (fd_backup - newest!),
I hope the picture is self explanatory.
Child processes will die anyway and all their fds will be closed (so no issue with them). But the parent process is left with 3 opened fds and they keep growing with each pipe executed.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…