C 具有两个子进程的fork()和wait()

C 具有两个子进程的fork()和wait(),c,unix,fork,wait,C,Unix,Fork,Wait,我需要使用fork()和wait()函数来完成作业。我们正在对非确定性行为进行建模,如果存在多个可能的转换,则需要程序执行fork() 为了尝试找出fork和wait是如何工作的,我刚刚编写了一个简单的程序。我想我现在了解了调用的工作原理,如果程序只分支一次就可以了,因为父进程可以使用单个子进程的退出状态来确定子进程是否达到接受状态 从下面的代码中可以看出,我希望能够处理必须有多个子进程的情况。我的问题是,您似乎只能使用退出功能设置一次状态。因此,在我的示例中,父进程测试的退出状态显示第一个子进

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

为了尝试找出
fork
wait
是如何工作的,我刚刚编写了一个简单的程序。我想我现在了解了调用的工作原理,如果程序只分支一次就可以了,因为父进程可以使用单个子进程的退出状态来确定子进程是否达到接受状态

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

我试图简单地不在拒绝上使用
\u 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;
}
#包括
#包括
#包括
#包括
#包括
内部主(空){
pid_t child_pid,wpid,pid;
int status=0;
int i;
int a[3]={1,2,1};
对于(i=1;i<3;i++){
printf(“i=%d\n”,i);
pid=getpid();
printf(“在i=%d\n之后的pid”,pid);
if((child_pid=fork())==0){
printf(“在子进程中\n”);
pid=getpid();
printf(“子进程中的pid为%d\n”,pid);
/*这是一个子进程*/
if(a[i]<2){
printf(“应接受”\n);
_出口(1);
}否则{
printf(“应被拒绝\n”);
_出口(0);
}
}
}
如果(子项pid>0){
/*是父进程吗*/
pid=getpid();
printf(“父\u pid=%d\n”,pid);
wpid=等待(&status);
如果(wpid!=-1){
printf(“孩子的退出状态为%d\n”,状态);
如果(状态>0){
printf(“接受”);
}否则{
printf(“完整的父进程\n”);
if(a[0]<2){
printf(“接受”);
}否则{
printf(“拒绝”);
}
}
}
}
返回0;
}

将wait()函数放入循环中,等待所有子进程。如果没有更多的子进程可用,wait函数将返回-1,errno将等于ECHILD。

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

如果不希望进行正常的清理操作(例如刷新打开的文件流,包括
标准输出),则应仅使用
\u exit()
。有时可以使用
\u exit()
;这不是其中之一。(在本例中,您当然也可以简单地让子对象返回,而不是直接调用
exit()
,因为从
main()
返回等同于以返回的状态退出。但是,大多数情况下,您会在
main()
以外的函数中执行分叉等操作,然后执行
exit())
通常是合适的。)


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


出色的示例Jonathan Leffler,为了使您的代码在SLES上工作,我需要添加一个额外的头以允许pid\t对象:)

#包括

太好了。我理解。非常感谢。好的。我理解。非常感谢您的回复。再次感谢您抽出时间。太好了。在你发表第一篇文章后,我自己制作了一个破损的工作版本,但你的要整洁得多。Cheers@Joe如果这个回答对您最有帮助,那么您应该通过单击左侧的复选标记来接受它。@Richard:我考虑过这个问题,但由于问题指出这是一个简化的示例,可以整理进程间同步的详细信息,我的结论是,这并不是填鸭式地回答家庭作业。@乔纳森:我只是在开玩笑。。。这是一个很好的问题,你的回答也很好。这很奇怪……POSIX 2008和我遇到的所有其他Linux系统都不需要
标题。
中的函数(如
getpid()
)需要在其声明中包含类型,因此不需要显式地包含
。你能说明你所使用的编译器选项是必要的
#include
?@JonathanLeffler我知道这是一个老评论,但SLES比其他的都老。就像红帽的艾尔。这就是我想的原因。
#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;
}
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)
#include <sys/types.h>