Jinz
Jinz

Reputation: 3

After a pipe() and fork(), why does close(fd[1]) in the parent close the *child's* fd[1]?

In the parent process close(fd[1]);,
why it will skip the first fd[1] (replaced parent STD_OUT) and close fd[1] at child process ?

#define STD_INPUT 0
#define STD_OUTPUT 1
int fd[2];
pipe(fd[0]);

if(fork()!=0){
    // parent process
    close(fd[0]);
    close(STD_OUTPUT);
    dup(fd[1]);
    close(fd[1]);
    excel(process1, process1, 0);
}
else{
    // child process
    // ...
}

UPDATE
It will have 2 fd[1] after dup(fd[1];,
why the system closed the second fd[1](4. [write]) in the result? not first fd[1](2. [write])?

start fork
1. STD_IN
2. STD_OUT
3. [read]
4. [write]

result
1. STD_IN
2. [write]
3. -close-
4. -close-

Upvotes: 0

Views: 483

Answers (1)

David Schwartz
David Schwartz

Reputation: 182753

It will have 2 fd[1] after dup(fd[1];,

No. The value of fd[1] never changes. If it was 4 before the call to dup, it's 4 after the call to dup.

why the system closed the second fd[1](4. [write]) in the result? not first fd[1](2. [write])?

If fd[1] is 4, then close(fd[1]); will close descriptor 4. It will not affect any other descriptors that happen to reference the same endpoint.

Before you call pipe, your process already has file descriptors 0, 1, and 2 as its standard input, standard output, and standard error. You then create two new descriptors for the pipe.

So this is what it looks like when you call fork, more or less:

...0...|....1....|.....2....|....fd[0]....|.....fd[1].....
stdin, stdout, stderr, pipe end, other pipe end

Then, in the parent, you close fd[0], so you have:

...0...|....1.....|.....2...|....fd[0]................|......fd[1].....
stdin, stdout, stderr, closed pipe end, open pipe end

Then you close stdout:

...0....|...1....|.....2.....|...fd[0]..|......fd[1].....
stdin, closed, stderr, closed, open pipe end

Then you dup the open pipe end:

...0....|..................1.............|.....2.....|..fd[0]..|.......fd[1].....
stdin, dup of open pipe end, stderr, closed, open pipe end

Then you close fd[1]:

...0....|....................1............|.....2...|...fd[0]..|..fd[1].....
stdin, dup of open pipe end, stderr, closed, closed

Or, more simply:

...0...|...................1...............|....2....
stdin, dup of open pipe end, stderr

So when you call execl, the new process will inherit the parent's standard input and standard error but will inherit a copy of one end of its pipe as its standard output.

Upvotes: 2

Related Questions