C程序中的fork vs vfork功能

the*_*age 2 c fork vfork

我正在做一些自我学习的C练习,并遇到了以下问题:

第一部分:

int main(int argc, char **argv) {                                         

    int a = 5, b = 8;                                                     
    int v;                                                                

    v = fork();                                                           
    if(v == 0) {                                                          
        // 10                                                             
        a = a + 5;                                                        
        // 10                                                             
        b = b + 2;                                                        
        exit(0);                                                          
    }                                                                     
    // Parent code                                                        
    wait(NULL);                                                           
    printf("Value of v is %d.\n", v); // line a                           
    printf("Sum is %d.\n", a + b); // line b                              
    exit(0);                                                              

} 
Run Code Online (Sandbox Code Playgroud)

b部分:

int main(int argc, char **argv) {                                         

    int a = 5, b = 8;                                                     
    int v;                                                                

    v = vfork();                                                               
    if(v == 0) {                                                          
        // a = 10                                                         
        a = a + 5;                                                        
        // b = 6                                                          
        b = b - 2;                                                        
        exit(0);                                                          
    }                                                                     
    // Parent code                                                        
    wait(NULL);                                                           
    printf("Value of v is %d.\n", v); // line a                           
    printf("Sum is %d.\n", a + b); // line b                              
    exit(0);                                                              

}
Run Code Online (Sandbox Code Playgroud)

我们要的输出比较line aline b.

a部分的输出是:

Value of v is 79525.
Sum is 13.
Run Code Online (Sandbox Code Playgroud)

b部分的输出是:

Value of v is 79517.
Sum is 16.
Run Code Online (Sandbox Code Playgroud)

它出现在部分a中,总和是初始声明ab的总和,而在部分b中,总和包括子进程中的总和.

我的问题是 - 为什么会发生这种情况?

根据这篇文章:

两者之间的基本区别在于,当使用vfork()创建新进程时,父进程将暂时挂起,子进程可能会借用父进程的地址空间.这种奇怪的状态一直持续到子进程退出或调用execve(),此时父进程继续.

父进程的定义暂时中止对我来说没有多大意义.这是否意味着,1b在父运行之前,程序会等到子进程完成运行(因此子进程变量求和的原因)?

问题陈述还假定"内核维护的父进程的进程ID是2500,并且在创建子进程之前由操作系统创建新进程".

根据这个定义,v两个计划的价值是什么?

mis*_*mer 5

父进程暂时中止

基本上,父进程在子进程调用其中_exit一个exec函数或其中一个函数之前不会运行.在您的示例中,这意味着子项将运行,因此在父项运行并执行打印之前执行求和.

至于:

我的问题是 - 为什么会发生这种情况?

首先,你的b部分有未定义的行为,因为你违反了vfork语义.程序的未定义行为意味着程序不会以可预测的方式运行.有关更多详细信息,请参阅有关未定义行为的SO帖子(它包含一些C++,但大多数想法都相同).从POSIX规范vfork:

vfork()函数与fork(2)具有相同的效果,除非如果vfork()创建的进程修改除了用于存储vfork()的返回值的pid_t类型的变量之外的任何数据,则行为未定义. ,或从调用vfork()的函数返回,或在成功调用_exit(2)或exec(3)函数系列之前调用任何其他函数.

所以你的b部分真的可以做任何事情.但是,您可能会看到b部分的输出有些一致.这是因为当您使用时,vfork您不会创建新的地址空间.相反,子进程基本上"借用"父进程的地址空间,通常意图是它将调用其中一个exec函数并创建一个新的程序映像.而是在您的部分b中使用父地址空间.基本上,在孩子打电话后exit(因为它应该打电话也是无效的_exit),a很可能会等于10并且b很可能在父母中等于6 .因此,总和为16,如b部分所示.我说的很可能是因为如前所述,这个程序有不确定的行为.

对于使用where的部分fork,子项获得自己的地址空间,并且在父项中看不到其修改,因此打印的值为13(5 + 8).

最后关于价值v,这似乎只是一个问题,说明使其显示的输出有意义.值v可以是由vfork或返回的任何有效值,fork并且不必限制为2500.

  • @ user3629249实际上,规范说调用任何函数但是_exit和exec变体是未定义的行为,你刚才说的原因是它为什么不好.孩子没有自己的地址空间,所以它会在父母的内存上进行清理,例如真正属于父母的刷新缓冲区. (2认同)