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

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

Моя теория заключается в следующем, и мне просто нужно разъяснение, чтобы я встал на правильный путь. Это непроверенный код, я просто написал его, чтобы вы поняли, о чем я думаю. Спасибо, любая помощь приветствуется.

int main(void){
    int fd[2][2]; //2 pipes for in/out

    //make the pipes
    pipe(fd[0]); //WRITING pipe
    pipe(fd[1]); //READING pipe

    if(fork() == 0){
        //child
        //close some ends
        close(fd[0][1]); //close the WRITING pipe write end
        close(fd[1][0]); //close the READING pipe read end

        //start the worker which will read from the WRITING pipe
        //and write back to the READING pipe
        start_worker(fd[0][0], fd[1][1]);
    }else{
        //parent
        //close the reading end of the WRITING pipe
        close(fd[0][0]);
        //close the writing end of the READING pipe
        close(fd[1][1]);
        //write data to the child down the WRITING pipe
        write(fd[0][1], "hello\n", 6);

        //read from the READING pipe 
        int nbytes;
        char word[MAX];
        while ((nbytes = read(fd[1][0], word, MAXWORD)) > 0){
            printf("Data from child is: %s\n", word);
        }
    }

}
1
1337holiday 20 Мар 2013 в 03:00

1 ответ

Лучший ответ

Сам канал не дублируется при вилке.

Один канал является однонаправленным и имеет 2 дескриптора - один для чтения, один для записи. Итак, в процессе A вы закрываете, например, дескриптор записи, в процессе B вы закрываете дескриптор чтения -> у вас есть канал от B до A.

Закрытие дескриптора в одном процессе не влияет на дескриптор в другом процессе. После разветвления у каждого процесса появляется собственное пространство дескрипторов, которое является копией дескрипторов родительского процесса. Вот выдержка из справочной страницы fork ():

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

2
Code Painters 20 Мар 2013 в 03:05
Правильно, это немного проясняет, можете ли вы пояснить, что я закрываю правильные файловые дескрипторы как в родительском, так и в дочернем?
 – 
1337holiday
20 Мар 2013 в 03:19
Да, по крайней мере, на первый взгляд выглядит прилично. Есть ли проблемы с его запуском?
 – 
Code Painters
20 Мар 2013 в 12:15