如何解决为什么我的 waitpid() 在进行后台进程后不等待孩子
我编写了这个简单的程序,它无休止地要求用户输入,然后使用 fork() 创建另一个进程来执行“ls -la”。
当用户输入为 0 时,进程被创建为后台进程。如果用户输入是其他任何内容,则父进程等待子进程终止。
在每次迭代中,僵尸进程都会被终止。这似乎工作得很好
这段代码的问题是:当后台进程被创建时,任何后续进程的父进程都不再等待。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
void delete_zombies(void)
{
pid_t kidpid;
int status;
while ((kidpid = waitpid(-1,&status,WNOHANG)) > 0)
{
printf("Child %ld terminated\n",kidpid);
}
}
int main() {
int runBGflag =0;
while(1)
{
scanf("%d",&runBGflag); //get user input
if (runBGflag==0) printf("making a child process and wait for it to finish\n");
else printf("making a background process\n");
pid_t pid; //fork
pid = fork();
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(-1,0) == pid && WIFEXITED(status))
{
printf("child dead. parent continues\n");
}
}
if (pid == 0) //Child process. Executes commands and prints error if something unexpected happened
{
execlp ("ls","-la",NULL);
printf ("exec: %s\n",strerror(errno));
exit(1);
}
delete_zombies();
}
}
我期待输出
E.G.我希望在输入 010 后有以下输出
0
making a child process and wait for it to finish
CMakeCache.txt cmake_install.cmake sigchild Testing
CMakeFiles Makefile sigchild.cbp
child dead. parent continues
1
making a background process
CMakeCache.txt cmake_install.cmake sigchild Testing
CMakeFiles Makefile sigchild.cbp
0
making a child process and wait for it to finish
CMakeCache.txt cmake_install.cmake sigchild Testing
CMakeFiles Makefile sigchild.cbp
child dead. parent continues
然而我只得到
0
making a child process and wait for it to finish
CMakeCache.txt cmake_install.cmake sigchild Testing
CMakeFiles Makefile sigchild.cbp
child dead. parent continues
1
making a background process
CMakeCache.txt cmake_install.cmake sigchild Testing
CMakeFiles Makefile sigchild.cbp
0
making a child process and wait for it to finish
CMakeCache.txt cmake_install.cmake sigchild Testing
CMakeFiles Makefile sigchild.cbp
解决方法
您正在等待这部分中的任何子进程:
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(-1,&status,0) == pid && WIFEXITED(status))
{
printf("child dead. parent continues\n");
}
}
因此,这里可能更正了“后台进程”而不是新进程。 “后台进程”应该与新进程有不同的pid,所以可能不会打印消息“child dead...”。
这可以通过插入这样的调试打印语句来验证:
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
pid_t ret = waitpid(-1,0);
printf("debug: expected %d,actual %d\n",(int)pid,(int)ret);
if (ret == pid && WIFEXITED(status))
{
printf("child dead. parent continues\n");
}
}
为避免这种情况,您应该通过 waitpid()
的第一个参数指定要等待的进程,如下所示:
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid,0) == pid && WIFEXITED(status))
{
printf("child dead. parent continues\n");
}
}
,
如果您运行孩子的目的是等待它,您实际上并没有等待那个特定的孩子,而是等待任何的孩子。如果有一个先前启动且未等待的子项,则可以改为收集该子项。
你想要更像这样的东西:
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid,0) == pid && WIFEXITED(status)) // CHANGED
{
printf("child dead. parent continues\n");
}
}
另请注意,WIFEXITED(status)
测试正在报告的进程是否正常终止。这不包括那些被信号杀死的人,尽管如此,它们仍然是死的。它也不包括那些已经停止但没有终止的——那些没有死,但你的程序无论如何都会停止等待它们。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。