fork() 和 wait() 带有两个子进程 [英] fork() and wait() with two child processes

查看:25
本文介绍了fork() 和 wait() 带有两个子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to use the fork() and wait() functions to complete an assignment. We are modelling non-deterministic behavior and need the program to fork() if there is more than one possible transition.

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

In order to try and work out how fork and wait work, I have just made a simple program. I think I understand now how the calls work and would be fine if the program only branched once because the parent process could use the exit status from the single child process to determine whether the child process reached the accept state or not.

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

As you can see from the code that follows though, I want to be able to handle situations where there must be more than one child processes. My problem is that you seem to only be able to set the status using an _exit function once. So, as in my example the exit status that the parent process tests for shows that the first child process issued 0 as it's exit status, but has no information on the second child process.

我只是尝试在拒绝时不使用 _exit()-ing,但是该子进程会继续执行,实际上似乎有两个父进程.

I tried simply not _exit()-ing on a reject, but then that child process would carry on, and in effect there would seem to be two parent processes.

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

Sorry for the waffle, but I would be grateful if someone could tell me how my parent process could obtain the status information on more than one child process, or I would be happy for the parent process to only notice accept status's from the child processes, but in that case I would successfully need to exit from the child processes which have a reject status.

我的测试代码如下:

#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
", i);
        pid = getpid();
        printf("pid after i = %d
", pid);
        if((child_pid = fork()) == 0)  {
            printf("In child process
");
            pid = getpid();
            printf("pid in child process is %d
", pid);
            /* Is a child process */
            if(a[i] < 2)  {
                printf("Should be accept
");
                _exit(1);
            } else  {
                printf("Should be reject
");
                _exit(0);
            }
        }
    }

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

推荐答案

在我看来,基本的问题是你有一个 wait() 调用,而不是一个等待直到出现的循环不再是孩子.您也只在最后一个 fork() 成功时才等待,而不是在至少一个 fork() 成功时等待.

It looks to me as though the basic problem is that you have one wait() call rather than a loop that waits until there are no more children. You also only wait if the last fork() is successful rather than if at least one fork() is successful.

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

You should only use _exit() if you don't want normal cleanup operations - such as flushing open file streams including stdout. There are occasions to use _exit(); this is not one of them. (In this example, you could also, of course, simply have the children return instead of calling exit() directly because returning from main() is equivalent to exiting with the returned status. However, most often you would be doing the forking and so on in a function other than main(), and then exit() is often appropriate.)

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

Hacked, simplified version of your code that gives the diagnostics I'd want. Note that your for loop skipped the first element of the array (mine doesn't).

#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
", getpid());
    for (i = 0; i < 3; i++)
    {
        printf("i = %d
", i);
        if ((child_pid = fork()) == 0)
        {
            printf("In child process (pid = %d)
", getpid());
            if (a[i] < 2)
            {
                printf("Should be accept
");
                exit(1);
            }
            else
            {
                printf("Should be reject
");
                exit(0);
            }
            /*NOTREACHED*/
        }
    }

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

示例输出(MacOS X 10.6.3):

Example output (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)

这篇关于fork() 和 wait() 带有两个子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆