我很小心地关闭了两个进程都没有使用的所有描述符
不是真的。
dup2(fd[1], STDOUT_FILENO);
这是你做的
stdout
副本
fd[1]
。
close(fd[1]);
在这里,您可以关闭
fd【1】
但是
标准装置
仍然打开。
那你呢
fork
。此时,两个进程都可以通过
标准装置
。
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
在复制的子进程中
fd[0]
到
stdin
并关闭
fd[0]
。
然后,当你执行
more
,它仍然可以访问管道的两端(通过
标准DIN
/
标准装置
)。
同时,您的父进程可以访问管道的两端(通过
fd[0]
/
标准装置
)。
实际上,你什么都没关。
还有第二个问题:父进程写入
标准装置
,它绑定到管道的写入端,没有任何人阅读它。取决于你写了多少
标准装置
是行缓冲还是块缓冲
标准装置
缓冲区是,以及管道本身可以存储多少,这本身可能会导致死锁。如果管道已满,周围没有人阅读,
printf
只会阻塞。
要解决此问题,请不要
dup2
并且在子进程启动之前不要写入管道。
int main(void){
int fd[2];
if (pipe(fd) == -1){
perror("Error creating pipe");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("Error spawning process");
return 2;
}
if (pid == 0) {
close(fd[1]); /* close write end of the pipe in the child */
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execlp("more", "more", (char*)NULL);
fprintf(stderr, "Failed to execute 'more'\n");
exit(1);
}
close(fd[0]); /* close read end of the pipe in the parent */
FILE *fp = fdopen(fd[1], "w");
if (!fp) {
perror("Error opening file handle");
return 3;
}
for (int i = 1; i <= 100; i++){
fprintf(fp, "Line %d\n", i);
}
fclose(fp); /* flush and close write end of the pipe in the parent */
wait(NULL);
return 0;
}