为什么不用fork()分割的进程通过这个函数进行相同的操作?

new*_*int 4 c c++

我对C/C++中的fork()函数感到困惑.给出以下代码:

void fork2()
{
    printf("LO\n");
    fork()
    printf("L1\n");
    fork();
    printf("Bye!\n");
}
Run Code Online (Sandbox Code Playgroud)

讲座幻灯片给出了下图

         ______Bye
   ___L1|______Bye
  |      ______Bye
L0|___L1|______Bye
Run Code Online (Sandbox Code Playgroud)

对我来说,这个图没有任何意义.我希望每次调用fork都会导致调用printf("LO\n").还是我错了?

Car*_*rum 15

你错了.在分叉时,父进程和子进程都从同一个地方继续 - 调用之后fork(),而不是在函数的开头.验证此行为很容易 - 将函数名称更改为main(),然后编译并运行它:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    printf("LO\n");
    fork();
    printf("L1\n");
    fork();
    printf("Bye!\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

LO
L1
Bye!
L1
Bye!
Bye!
Bye!
Run Code Online (Sandbox Code Playgroud)

没有什么比实际尝试一些东西来弄清楚它是如何工作的......

  • 很好的答案.另请注意,由于上下文切换,OS调度程序可能会导致打印顺序不是您所期望的. (5认同)

Bar*_*art 7

你错了.:) fork之后,两个进程都将执行fork之后的下一条指令.


Cor*_*ein 7

fork()创建一个与fork()函数调用的进程完全相同的副本.这意味着,您有两个完全相同的进程,并且在程序中处于同一点.如果我们单步执行fork2()函数,则会发生以下情况.

过程A(原始过程):
L0(过程A分叉,创建过程B)
L1(过程A再次分叉,创建过程C)
再见!(进程A退出)

过程B:
L1(过程B分叉,创建过程D)
再见!(进程B退出)

过程C:
再见!(进程C退出)

过程D:
再见!(进程D退出)

操作系统取决于它在每个分支处进行哪个进程,以及它是否在运行时间期间的任何时刻切换到另一个进程,因此输出可以在进程分支之后的任何点交错.例如,如果操作系统选择始终跟随新进程直到函数结束,您将获得以下输出:

L0   (A)  
L1   (B)  
Bye! (D)  
Bye! (B)  
L1   (A)  
Bye! (C)  
Bye! (A)
Run Code Online (Sandbox Code Playgroud)


Fré*_*idi 5

的行为fork(),需要一些时间来适应,因为它实际上也派生的执行路径进入父子进程(它返回0子进程和子进程的父进程的PID).

这意味着在第一次调用之后fork(),您将有两个进程运行相同的代码,在第二次调用之后,您将有四个进程(因为两个进程都发出了fork()调用),仍然运行相同的代码.因此,图表:

     L0
    /   \
   /     \
  L1      L1
 /  \    /  \
Bye Bye Bye Bye
Run Code Online (Sandbox Code Playgroud)