为什么我的 waitpid() 在创建后台进程后不等待 child
Why does my waitpid() not wait for child after making a background process
我写了这个简单的程序,它无休止地要求用户输入,然后用 fork() 创建另一个进程来执行“ls -la”。
当用户输入为 0 时,该进程被创建为后台进程。如果用户输入的是其他内容,parent 进程将等待 child 进程终止。
在每次迭代中,僵尸进程都会被终止。这似乎工作得很好
这段代码的问题是:创建后台进程时,任何后续进程的parent进程不再等待。
#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, &status, 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();
}
}
我期待输出
我希望在输入 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, &status, 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, &status, 0) == pid && WIFEXITED(status))
{
printf("child dead. parent continues\n");
}
}
如果您 运行 child 打算等待它,您实际上并没有等待那个特定的 child,而是 任何child。如果有之前发布的和unwaited-for child那么可以代为收集。
你想要更像这样的东西:
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) // CHANGED
{
printf("child dead. parent continues\n");
}
}
另请注意,WIFEXITED(status)
测试报告的进程是否正常 终止。这不包括那些被信号杀死的,但它们仍然是死的。它也不包括那些已经停止但没有终止的——那些没有死,但你的程序无论如何都会停止等待它们。
我写了这个简单的程序,它无休止地要求用户输入,然后用 fork() 创建另一个进程来执行“ls -la”。
当用户输入为 0 时,该进程被创建为后台进程。如果用户输入的是其他内容,parent 进程将等待 child 进程终止。
在每次迭代中,僵尸进程都会被终止。这似乎工作得很好
这段代码的问题是:创建后台进程时,任何后续进程的parent进程不再等待。
#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, &status, 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();
}
}
我期待输出
我希望在输入 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, &status, 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, &status, 0) == pid && WIFEXITED(status))
{
printf("child dead. parent continues\n");
}
}
如果您 运行 child 打算等待它,您实际上并没有等待那个特定的 child,而是 任何child。如果有之前发布的和unwaited-for child那么可以代为收集。
你想要更像这样的东西:
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) // CHANGED
{
printf("child dead. parent continues\n");
}
}
另请注意,WIFEXITED(status)
测试报告的进程是否正常 终止。这不包括那些被信号杀死的,但它们仍然是死的。它也不包括那些已经停止但没有终止的——那些没有死,但你的程序无论如何都会停止等待它们。