Я изучаю 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);
}
}
}
Я дам список того, что я сейчас понимаю:
- Я понимаю, что родительский и дочерний процессы должны закрывать те файлы, которые им не нужны, в этом случае дочерний процесс выполняет запись в родительский процесс, поэтому родительский процесс должен закрыть порт записи, а дочерний должен закрыть порт чтения.
- Я понимаю, что файловые дескрипторы совместно используются родительским процессом и дочерним процессом.
Приведенный выше код взят из моего лекционного слайда, меня смущает одна вещь.
В цикле я наблюдаю, что каждый дочерний элемент закрывает свой порт чтения после того, как этот дочерний элемент создан 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);
}
}
Я не понимаю, почему последние дети должны закрывать порт чтения предыдущих детей, разве эти порты чтения уже не закрыты после создания этих детей?
Спасибо за помощь. :)