Почему после pipe () и fork () родительский объект close (fd [1]) закрывает * child's * fd [1]? - PullRequest
0 голосов
/ 22 марта 2019

В родительском процессе close(fd[1]);,
почему он пропустит первый fd [1] (заменил родительский STD_OUT) и закроет fd [1] при дочернем процессе?

#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
У него будет 2 fd [1] после dup(fd[1];,
почему система закрыла второй fd [1] (4. [write]) в результате? не первый fd [1] (2. [запись])?

стартовый форк
1. STD_IN
2. STD_OUT
3. [читать]
4. [написать]

результат
1. STD_IN
2. [написать]
3. -close-
4. -close-

1 Ответ

2 голосов
/ 24 марта 2019

У него будет 2 fd [1] после dup (fd [1];,

Нет. Значение fd[1] никогда не меняется. Если оно было 4 до вызована dup, это 4 после вызова dup.

, почему система закрыла второй fd [1] (4. [write]) в результате? не первый fd [1] (2. [Запись])?

Если fd[1] равно 4, то close(fd[1]); закроет дескриптор 4. Это не повлияет на другие дескрипторы, которые ссылаются на одну и ту же конечную точку.

Перед вызовом pipe ваш процесс уже имеет дескрипторы файлов 0, 1 и 2 в качестве стандартного ввода, стандартного вывода и стандартной ошибки. Затем вы создаете два новых дескриптора для канала.

Вот как это выглядит, когда вы звоните fork, более или менее:

... 0 ... | .... 1 .... | .....2 .... | .... fd [0] .... | ..... fd [1] .....
stdin, stdout, stderr, конец трубы, другой конец трубы

Затем в родительском элементе вы закрываете fd[0], поэтому у вас есть:

... 0 ... | .... 1 ..... | ..... 2 ... | .... FD [0] ................ | ...... fd [1] .....
stdin, stdout, stderr, закрытый конец трубы, открытый конец трубы

Тогда вызакрыть стандартный вывод:

... 0 .... | ... 1 .... | ..... 2 ..... | ... fd [0].. | ...... fd [1] .....
stdin, закрыто, stderr, закрыто, открытый конец трубы

Затем вы дублируете открытый конец трубы:

... 0 .... | .................. 1 ............. |..... 2 ..... | ..fd [0] .. | ....... fd [1] .....
stdin, дублирование открытого конца трубы, stderr, закрытое, открытый конец трубы

Затем закройте fd [1]:

... 0 .... | .................... 1 ............ | ..... 2 ... | ... FD [0] .. | ..fd [1].....
stdin, дублирование открытого конца трубы, stderr, закрыто, закрыто

Или, проще:

... 0 ...| ................... 1 ............... | .... 2 ....
stdin, dup открытого конца канала, stderr

Так что, когда вы вызываете execl, новый процесс унаследует стандартный ввод и стандартную ошибку родителя, но унаследует копию одного конца своего канала какстандартвыход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...