Почему, когда я использую dup2 () перед fork (), он не работает? - PullRequest
1 голос
/ 20 марта 2019

Я хочу сделать оболочку, и я хочу обрабатывать несколько труб.Я пытался понять, как работает dup2 () и fork.Обычно fork () создает новый дочерний процесс, который точно такой же, как и отец.Но когда я использую dup2 перед разветвлением, кажется, что он не работает так, как должен.Но когда я использую dup2 () в дочернем процессе, он работает ... Я не понимаю, потому что обычно fork создает копию вызывающего процесса ...

Может кто-нибудь объяснить, почему?

Это не работает:

int fd = open("toto.txt", O_RDONLY);
char str[10] = {0};
int test[2] = {0, 0};
char *av[] = {"/bin/ls", NULL};

pipe(test);
dup2(test[1], 1);
if (fork() == 0) {
    execve(av[0], av, env);
}
else {
    wait(NULL);
    read(test[0], str, 10);
    write(1, str, 10);
}

, но это работает:

int fd = open("toto.txt", O_RDONLY);
char str[10] = {0};
int test[2] = {0, 0};
char *av[] = {"/bin/ls", NULL};

pipe(test);
if (fork() == 0) {
    dup2(test[1], 1);
    execve(av[0], av, env);
}
else {
    wait(NULL);
    read(test[0], str, 10);
    write(1, str, 10);
}

1 Ответ

1 голос
/ 20 марта 2019

Оригинал не работает правильно, потому что:

dup2(test[1], 1);
if (fork() == 0) {
    execve(av[0], av, env);
}
else {
    wait(NULL);
    read(test[0], str, 10);
    write(1, str, 10);
}

После того, как стандартный вывод dup2 перенаправляется на канал. Это перенаправление применяется как к родителю, так и к ребенку. В связи с этим линия:

    write(1, str, 10);

записывает свои данные обратно в канал, а не в исходный стандартный вывод (который потерян).

Перемещая dup2 после fork() и только в дочерний процесс, исходный стандартный вывод родительского элемента остается один. В этом случае перенаправляется только стандартный вывод ребенка.

Примечание: вызов wait перед чтением канала будет работать для небольшого канала, как в примере, но не будет работать для большого трафика. Проблема в том, что канал имеет ограниченный буфер. Как только буфер заполнен, канал начинает блокировать записи. wait будет ожидать завершения дочернего процесса, но дочерний процесс будет ожидать в канале, который будет прочитан родительским элементом. Это может стать тупиком, когда трафик достаточно большой.

...