微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我的 waitpid() 在进行后台进程后不等待孩子

如何解决为什么我的 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 举报,一经查实,本站将立刻删除。