C语言多进程程序为何在wait(NULL)处阻塞?
问题:父进程卡在
wait(NULL)无法获取子进程strace输出 我是一名C语言初学者,编写了一个多进程程序,希望让子进程调用strace,再通过管道将输出传递给父进程进行打印。但父进程似乎卡在了wait(NULL);处,我尝试注释掉wait(NULL);后,就能正常获取子进程的输出。我无法理解父进程为何一直处于等待状态,子进程难道还没退出吗?
以下是我的代码:
#include <stdio.h> #include <sys/types.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char *argv[]) { int pipefd[2]; pid_t pid; char *exec_argv[] = { "/bin/strace", "-T", "tree", "/bin", NULL}; char *exec_envp[] = { "PATH=/bin", NULL }; if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } pid = fork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { // child close(pipefd[0]); /* close unused read end */ close(STDOUT_FILENO); if (dup2(pipefd[1], STDERR_FILENO) == -1) { perror("dup2"); exit(EXIT_FAILURE); } // invoke strace execve(exec_argv[0], exec_argv, exec_envp); perror(exec_argv[0]); exit(EXIT_FAILURE); } else { // parent close(pipefd[1]); /* close unused write end */ if (dup2(pipefd[0], STDIN_FILENO) == -1) { perror("dup2"); exit(EXIT_FAILURE); } printf("I'm parent!!!\n"); wait(NULL); char *line = NULL; size_t len; while (getline(&line, &len, stdin) != -1) { printf("%s", line); } free(line); } return 0; }
问题原因
这是管道读写阻塞导致的死锁:
- 子进程通过
dup2把stderr重定向到管道写端,strace的输出会持续往管道里写 - 父进程先调用
wait(NULL)等待子进程退出,但管道缓冲区有大小限制,当子进程把缓冲区写满后,会被阻塞,等待父进程读取管道数据 - 此时父进程在等子进程退出,子进程在等父进程读管道,双方互相等待,形成死锁
解决方法
调整父进程的代码逻辑,先读取管道数据,再等待子进程退出:
else { // parent close(pipefd[1]); /* close unused write end */ if (dup2(pipefd[0], STDIN_FILENO) == -1) { perror("dup2"); exit(EXIT_FAILURE); } printf("I'm parent!!!\n"); // 先读取管道数据,子进程写完后会自动退出 char *line = NULL; size_t len; while (getline(&line, &len, stdin) != -1) { printf("%s", line); } free(line); wait(NULL); // 此时子进程已退出,wait不会阻塞 }
补充说明
- 管道的规则是:当所有读端关闭时,写端进程会收到
SIGPIPE信号退出;当所有写端关闭时,读端的getline会返回-1(表示EOF) - 原来的逻辑中,父进程没读管道,子进程写满缓冲区后卡住,导致
wait永远等不到子进程退出 - 调整顺序后,父进程持续读取管道数据,子进程可以顺利写完输出并退出,
wait就能正常获取子进程的退出状态
内容的提问来源于stack exchange,提问作者sir chen
相关产品推荐
相关产品推荐

