简体   繁体   English

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

[英]fork() and wait() with two child processes

I need to use the fork() and wait() functions to complete an assignment. 我需要使用fork()和wait()函数来完成赋值。 We are modelling non-deterministic behaviour and need the program to fork() if there is more than one possible transition. 我们正在对非确定性行为进行建模,如果存在多个可能的转换,则需要fork()程序。

In order to try and work out how fork and wait work, I have just made a simple program. 为了尝试解决fork和wait如何工作,我刚刚制作了一个简单的程序。 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. 我想现在我理解调用是如何工作的,并且如果程序只分支一次会很好,因为父进程可以使用单个子进程的退出状态来确定子进程是否达到接受状态。

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. 我的问题是你似乎只能使用_exit函数设置状态一次。 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. 因此,在我的示例中,父进程测试的退出状态显示第一个子进程在其退出状态时发出0,但没有关于第二个子进程的信息。

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. 我试着简单地不是_exit() - 拒绝,但那个子进程会继续,实际上似乎有两个父进程。

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. 对于华夫饼干感到抱歉,但如果有人能告诉我父进程如何获取有关多个子进程的状态信息,我将不胜感激,或者我很高兴父进程只能注意到来自子进程的接受状态,但在这种情况下,我将成功地需要退出具有拒绝状态的子进程。

My test code is as follows: 我的测试代码如下:

#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;
}

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. 它看起来好像基本的问题是你有一个wait()调用,而不是一个等待,直到没有更多的孩子。 You also only wait if the last fork() is successful rather than if at least one fork() is successful. 您也只能等待最后一个fork()成功,而不是至少有一个fork()成功。

You should only use _exit() if you don't want normal cleanup operations - such as flushing open file streams including stdout . 如果您不想进行正常的清理操作,则应该只使用_exit() - 例如刷新包含stdout打开文件流。 There are occasions to use _exit() ; 有时候使用_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.) (在这个例子中,你当然也可以直接让孩子返回而不是直接调用exit() ,因为从main()返回相当于退出返回状态。但是,大多数时候你会做分叉和在main()以外的函数中等等,然后exit()通常是合适的。)


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). 请注意,你的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;
}

Example output (MacOS X 10.6.3): 示例输出(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)

Put your wait() function in a loop and wait for all the child processes. 将wait()函数放在循环中并等待所有子进程。 The wait function will return -1 and errno will be equal to ECHILD if no more child processes are available. 如果没有更多的子进程可用,则wait函数将返回-1并且errno将等于ECHILD。

精彩的例子Jonathan Leffler,为了让你的代码在SLES上运行,我需要添加一个额外的头来允许pid_t对象:)

#include <sys/types.h>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM