使用fork的偶数程序

问题描述 投票:0回答:2

我用fork编写了一个用于偶数和奇数的程序,它有时打印偶数,有时打印奇数。请解释这个问题?

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
        int i;
        if(fork() == 0)
        {
                for(i=1;i<50;i++)
                        if(i%2 == 0)
                                printf("even %d\n",i);
        }
        else
        {
                for(i=1;i<50;i++)
                        if(i%2 != 0)
                                printf("odd %d\n",i);
        }
}

我将得到如下输出:奇数1奇数3奇数5奇数7奇数9奇数11奇数13奇数15奇数17奇数19奇数21奇数23奇数25甚至2奇数27甚至4奇数29甚至6奇数31甚至8奇数33甚至十奇数35甚至十二奇数37甚至14奇数39甚至16奇数41甚至18奇数43甚至20奇数45甚至22奇数47甚至24奇数49即使26甚至28甚至30甚至32甚至34甚至36甚至38甚至40甚至42甚至44甚至46甚至48

c linux fork
2个回答
0
投票

[C0之后,将创建一个子进程。

[孩子的返回值为0,将打印偶数,而父母的孩子的进程ID作为fork()的返回值,并将打印奇数。

fork()

但是,父级和子级是两个进程,很难确定哪个先运行。它们可能使用不同的CPU内核,因此并行运行,或者仅在同一内核上运行。

实际上,当多个进程在同一个CPU内核上运行时,会有CPU调度。请注意,CPU内核不能同时做两件事。

CPU调度是确定在特定时间点运行哪个进程的方法。通常,一个进程在中断之前需要运行很短的时间,然后一直等待直到下一次获得资源。

计划运行的进程切换非常快(上下文切换),因此,作为人类,当另一个进程正在运行时,您不会感觉到该进程挂起。就像每个进程同时运行一样。

返回您的问题,在 int i; if(fork() == 0) { for(i=1;i<50;i++) if(i%2 == 0) printf("even %d\n",i); } else { for(i=1;i<50;i++) if(i%2 != 0) printf("odd %d\n",i); } 之前打印出一些偶数。例如,有odd 49,表示打印出odd 25 even 2后中断了父进程(要打印奇数)。然后,子进程获得了资源并在其后打印出odd 25

[每次奇数后跟偶数是由于父级在那里被打断。另一方面,当在偶数之后打印奇数时,这是因为子进程在那里被中断。


0
投票

[C0成功后,父进程和子进程将基本上同时执行。 (另一个答案指出,这是通过在两者之间进行快速上下文切换来实现的。)这些进程的输出可以随时到达输出流。

该问题的注释表明,期望子进程在父进程开始执行自己的even 2循环之前完成其fork()循环。为此,必须执行显式的forfor调用。这将导致父进程阻塞,直到子进程退出。

下面的修订代码显示了wait调用的包含。另请参见下面的输出,其中包含奇数之前的所有偶数。

其他注意事项:

  • waitpid输出经过stdio缓冲,但是这里不必显式调用waitpid以确保偶数在奇数之前被完全写入,因为这会在之前自动进行孩子退出。

  • 通过调用printf,父级还会通过作为第二个参数传递的fflush指针收集子级的退出状态。在问题代码中,永远不会调用waitpidint *。因此,如果子项恰好在父项退出之前退出,则其退出状态将保留在进程表中(作为“僵尸”进程),直到父项退出为止。在此示例中,父进程和子进程将在大约同一时间完成,但是通常,优良作法是确保派生子进程的父进程执行后续的等待调用(或执行wait来指示不需要孩子退出状态的内核)。

waitpid

输出:

signal(SIGCHLD, SIG_IGN);    
© www.soinside.com 2019 - 2024. All rights reserved.