Pipe: закрытие файловых дескрипторов в массиве pipe - PullRequest
0 голосов
/ 17 марта 2019

Я изучаю Linux и готовлю такие вещи для моего курса по системному программированию прямо сейчас, мне трудно понять, закрывать дескрипторы файлов в массиве каналов.

 // write the code to loop over the command line arguments (remember to skip the executable name)
for (int i = 1; i < argc; i++) {
    // call pipe before we fork
    if ((pipe(pipe_fd[i-1])) == -1) {
        perror("pipe");
        exit(1);
    }
    // call fork
    int result = fork();
    if (result < 0) {   // case: a system call error
        // handle the error
        perror("fork");
        exit(1);
    } else if (result == 0) {  // case: a child process
        // child does their work here
        // child only writes to the pipe so close reading end
        if (close(pipe_fd[i-1][0]) == -1) {
            perror("close reading end from inside child");
            exit(1);
        }
        // before we forked the parent had open the reading ends to
        // all previously forked children -- so close those
        int child_no;
        for (child_no = 0; child_no < i-1; child_no++) {
            if (close(pipe_fd[child_no][0]) == -1) {
                perror("close reading ends of previously forked children");
                exit(1);
            }
        }
        int len = strlen(argv[i]);
        // write len to the pipe as an integer
        if (write(pipe_fd[i-1][1], &len, sizeof(int)) != sizeof(int)) {
            perror("write from child to pipe");
            exit(1);
        }
        // I'm done with the pipe so close it
        if (close(pipe_fd[i-1][1]) == -1) {
            perror("close pipe after writing");
            exit(1);
        }
        // exit so I don't fork my own children on next loop iteration
        exit(0);
    } else {
        // in the parent but before doing the next loop iteration
        // close the end of the pipe that I don't want open
        if (close(pipe_fd[i-1][1]) == -1) {
            perror("close writing end of pipe in parent");
            exit(1);
        }
    }
}

Я дам список того, что я сейчас понимаю:

  1. Я понимаю, что родительский и дочерний процессы должны закрывать те файлы, которые им не нужны, в этом случае дочерний процесс выполняет запись в родительский процесс, поэтому родительский процесс должен закрыть порт записи, а дочерний должен закрыть порт чтения.
  2. Я понимаю, что файловые дескрипторы совместно используются родительским процессом и дочерним процессом.

Приведенный выше код взят из моего лекционного слайда, меня смущает одна вещь.

В цикле я наблюдаю, что каждый дочерний элемент закрывает свой порт чтения после того, как этот дочерний элемент создан fork, и код, который выполняет это действие:

else if (result == 0) {  // case: a child process
    // child does their work here
    // child only writes to the pipe so close reading end
    if (close(pipe_fd[i-1][0]) == -1) {
        perror("close reading end from inside child");
        exit(1);
    }

Из того, что я понимаю на данный момент, заключается в том, что каждый ребенок собирается закрыть свой собственный порт чтения после рождения вилкой, и я думаю, что последние созданные дети НЕ ДОЛЖНЫ беспокоиться о закрытии порта чтения предыдущих детей.

Но моё понимание кажется неправильным после прочтения этого кода:

        // before we forked the parent had open the reading ends to
    // all previously forked children -- so close those
    int child_no;
    for (child_no = 0; child_no < i-1; child_no++) {
        if (close(pipe_fd[child_no][0]) == -1) {
            perror("close reading ends of previously forked children");
            exit(1);
        }
    }

Я не понимаю, почему последние дети должны закрывать порт чтения предыдущих детей, разве эти порты чтения уже не закрыты после создания этих детей?

Спасибо за помощь. :)

1 Ответ

0 голосов
/ 17 марта 2019

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

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

...