通过一个简单的例子来理解C的fork()

时间:2013-03-07 04:04:28

标签: c fork concept

#include <stdio.h>
int num = 0;
int main(int argc, char*argv[]){
    int pid;
    pid = fork();
    printf("%d", num);  
    if(pid == 0){       /*child*/
        num = 1;
    }else if(pid > 0){  /*parent*/
        num = 2;
    }
    printf("%d", num);
}

我无法理解可能的输出为什么会这样 0102或0012或0201或0021.

这是我认为它应该产生的东西。它命中第一个printf语句,无论先执行什么子项或父项,num都没有被修改为0。那么接下来是1或2,然后执行下一个过程,所以再次从0开始(从父项复制),然后再次从1或2开始。所以可能的输出应该是:

0101或 0102或 0201或 0202

2 个答案:

答案 0 :(得分:10)

在父级和子级中,第一个printf的num为0。在父和子中,打印0,然后打印另一个值。在父进程中,另一个值为2.在子进程中,另一个值为1.

然而,需要注意的重要一点是,虽然每个流程都有一个强制订单,零必须在另一个数字之前打印,但两个流程相对于彼此的打印没有限制。

这是一个真实的比喻:假设我的同事和我同时离开工作,停在杂货店,然后到家。我知道我在家之前就在商店,我们知道他在家之前就在杂货店。但我们不知道谁先在杂货店,或者谁先在家。我们每个人都可以在同一时间到达杂货店,然后每个人大约在同一时间到家,或者他可能会被推迟,我甚至可以在去商店之前到杂货店和家里去。

不会发生的事情是不止一次打印1或2。虽然在fork返回后,我们有两个进程在概念上同时运行,并且它们的事件相对于彼此的时间是未指定的,但是每个进程中的事件顺序都已明确定义。在再次打印之前,每个进程都会将num设置为1或2,并且因为fork被定义为在子节点中返回0而子节点中的子节点pid,它们将每个进程设置为不同的值

实际上,还有另一个合理的输出:00。如果fork无法创建新进程,则返回-1。在这种情况下,程序将打印0ifelse if将失败,因为-1既不是0也不是大于0,num没有更改,程序打印{{1再次。

如果你想学习很多关于C程序中效果排序的定义,搜索的关键词是“序列点”。在这个程序中它是相当简单的(除了我们一次运行两个副本的事实),但它有时可能不太明显。

答案 1 :(得分:9)

这不是fork()的问题。自printf()缓存以来printf()。通常,缓冲区在最后遇到换行符时会被刷新,'\ n'。但是,由于您省略了这一点,缓冲区的内容会保留并且不会被刷新。最后,两个进程(原始进程和子进程)将具有0或1的输出缓冲区。当它最终被刷新时,你会在两个过程中看到这一点。

fflush(stdout);之后添加printf()并尝试。