Проблема с трубами между отцом и сыном процессов - PullRequest
0 голосов
/ 11 апреля 2019

Используя каналы, отец читает из стандартного ввода и отправляет его в дочерний процесс, используя каналы, чтобы дочерний элемент мог выполнить wordcount для ввода. Проблемы с открытой и закрытой трубой p [0] и p [1]. Почему я не могу dup2 (p [1], 1) и затем написать (1, buffer, 1)? Это работает, только если я пишу (p [1], buffer, 1) без dup2 (p [1], 1).

int main(int argc, char **argv){
    int p[2];
    int n;
    char buffer[1024];
    pipe(p);
    if(!fork()){
        close(p[1]);    
        dup2(p[0],0);
        close(p[0]);
        execlp("wc","wc",NULL);
        _exit(0);
    }
    else{
        close(p[0]);
        dup2(p[1],1);
        while((n=read(0,buffer,1))>0){
            write(1,buffer,1);
        }
        close(p[1]);
        wait(NULL);
    }
    return 0;
}

1 Ответ

0 голосов
/ 11 апреля 2019

Почему я не могу дублировать 2 (p [1], 1), а затем записать (1, буфер, 1)?

Можно, хотя это кажется бессмысленным. Однако было бы более разумно, если бы вы пытались использовать одну из функций ввода-вывода, которая записывает (только) в стандартный вывод.

Это работает, только если я пишу (p [1], buffer, 1) без dup2 (p [1], 1).

Это зависит от того, что вы подразумеваете под «делами». Когда я запускаю ваш исходный код, программа никогда не печатает никаких выходных данных и никогда не завершается, но это не означает, что записи родителя не успешно отправили данные дочернему элементу.

Проблема в том, что ребенок не знает, когда достигнут конец ввода. Он ожидает сигнала конца файла на своем входе, который не будет поступать, пока есть любые дескрипторы открытого файла, связанные с концом записи канала.

Если родительский объект не дублирует конец записи канала, то у него открыт только один дескриптор файла, а у дочернего - один. Оба закрывают свои в подходящее время. Но в представленном вами коде родительский элемент помещает p[1] в файловый дескриптор 1, так что он имеет два открытых файловых дескриптора, относящихся к концу канала. Он закрывается только p[1], оставляя файловый дескриптор 1 открытым, поэтому ребенок продолжает ждать ввода.

Родитель закроет FD 1, если он выйдет, что позволит ребенку закончить, но ожидает, чтобы ребенок завершил сначала. Это одна из наиболее распространенных ошибок взаимоблокировок, связанных с перенаправлением ввода-вывода. Я бы предложил просто не иметь родительского дублирования файлового дескриптора, так как дублирование на FD 1 излишне мешает ему использовать стандартный вывод для каких-либо других целей. Но если он не работает, он должен закрыть оба файловых дескриптора, прежде чем дочерний процесс завершится.

...