c - fork() 和 wait() 有两个子进程

标签 c unix fork wait

我需要使用fork()wait() 函数来完成一个作业。我们正在对非确定性行为进行建模,如果存在不止一种可能的转换,则需要程序fork()

为了尝试弄清楚forkwait 是如何工作的,我刚刚编写了一个简单的程序。我想我现在明白了调用是如何工作的,如果程序只分支一次就没问题了,因为父进程可以使用单个子进程的退出状态来确定子进程是否达到接受状态。

正如您从下面的代码中看到的那样,我希望能够处理必须有多个子进程的情况。我的问题是您似乎只能使用一次 _exit 函数设置状态。因此,在我的示例中,父进程测试的退出状态显示第一个子进程发出 0 作为退出状态,但没有关于第二个子进程的信息。

我尝试简单地不 _exit()-ing 拒绝,但是子进程会继续,实际上似乎有两个父进程。

对不起,我很抱歉,但如果有人能告诉我我的父进程如何获得多个子进程的状态信息,我将不胜感激,或者我很高兴父进程只注意到来自子进程的接受状态子进程,但在那种情况下,我需要成功退出具有拒绝状态的子进程。

我的测试代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>

int main(void)  {

    pid_t child_pid, wpid, pid;
    int status = 0;
    int i;

    int a[3] = {1, 2, 1};
    for(i = 1; i < 3; i++)  {
        printf("i = %d\n", i);
        pid = getpid();
        printf("pid after i = %d\n", pid);
        if((child_pid = fork()) == 0)  {
            printf("In child process\n");
            pid = getpid();
            printf("pid in child process is %d\n", pid);
            /* Is a child process */
            if(a[i] < 2)  {
                printf("Should be accept\n");
                _exit(1);
            } else  {
                printf("Should be reject\n");
                _exit(0);
            }
        }
    }

    if(child_pid > 0)  {
        /* Is the parent process */
        pid = getpid();
        printf("parent_pid = %d\n", pid);
        wpid = wait(&status);
        if(wpid != -1)  {
            printf("Child's exit status was %d\n", status);
            if(status > 0)  {
                printf("Accept\n");
            } else  {
                printf("Complete parent process\n");
                if(a[0] < 2)  {
                    printf("Accept\n");
                } else  {
                    printf("Reject\n");
                }
            }
        }
    }
    return 0;
}

最佳答案

在我看来,基本问题似乎是您有一个 wait() 调用,而不是一个等待直到没有更多 child 的循环。您也只会在最后一个 fork() 成功时等待,而不是在至少一个 fork() 成功时等待。

如果您不想进行正常的清理操作,例如刷新打开的文件流,包括 stdout,您应该只使用 _exit()。有时需要使用 _exit();这不是其中的一个。 (在这个例子中,当然,您也可以简单地让 child 返回而不是直接调用 exit(),因为从 main() 返回等同于退出返回的状态。但是,大多数情况下,您会在 main() 以外的函数中执行 fork 等操作,然后 exit() 通常是合适的。)


经过黑客攻击的简化版代码可提供我想要的诊断信息。请注意,您的 for 循环跳过了数组的第一个元素(我的没有)。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(void)
{
    pid_t child_pid, wpid;
    int status = 0;
    int i;
    int a[3] = {1, 2, 1};

    printf("parent_pid = %d\n", getpid());
    for (i = 0; i < 3; i++)
    {
        printf("i = %d\n", i);
        if ((child_pid = fork()) == 0)
        {
            printf("In child process (pid = %d)\n", getpid());
            if (a[i] < 2)
            {
                printf("Should be accept\n");
                exit(1);
            }
            else
            {
                printf("Should be reject\n");
                exit(0);
            }
            /*NOTREACHED*/
        }
    }

    while ((wpid = wait(&status)) > 0)
    {
        printf("Exit status of %d was %d (%s)\n", (int)wpid, status,
               (status > 0) ? "accept" : "reject");
    }
    return 0;
}

示例输出(MacOS X 10.6.3):

parent_pid = 15820
i = 0
i = 1
In child process (pid = 15821)
Should be accept
i = 2
In child process (pid = 15822)
Should be reject
In child process (pid = 15823)
Should be accept
Exit status of 15823 was 256 (accept)
Exit status of 15822 was 0 (reject)
Exit status of 15821 was 256 (accept)

关于c - fork() 和 wait() 有两个子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2708477/

相关文章:

linux - Linux下只列出3个子目录的命令是什么

unix - Unix 管理员应该具备哪些编程能力?

mysql - C fork 在 5 个 child 后停止

c++ - 叉(): Dont return from child until it's terminated

c - 请详细告诉我为什么c代码会这样?

c - fdim 首字母缩写词代表什么?

c - 以下代码片段的输出是什么?为什么?

bash - 合并 CSV 文件 : Appending instead of merging

git - 如何使用 git 将多个项目 fork 到一个存储库中?

c - 如何将此 C 代码转换为汇编 IA32?