C程序中的fork vs vfork功能

时间:2015-08-02 19:50:28

标签: 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);                                                              

} 

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);                                                              

}

我们必须比较line aline b的输出。

a部分的输出是:

Value of v is 79525.
Sum is 13.

b部分的输出是:

Value of v is 79517.
Sum is 16.

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

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

根据post

  

两者之间的基本区别在于新的流程   使用vfork()创建,父进程暂时挂起,并且   子进程可能会借用父进程的地址空间。这个   奇怪的状况持续到孩子处理为止   退出,或调用execve(),此时父进程继续。

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

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

根据这个定义,两个程序的v值是多少?

1 个答案:

答案 0 :(得分:5)

  

父进程暂时中止

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

至于:

  

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

首先,你的b部分有未定义的行为,因为你违反了vfork语义。程序的未定义行为意味着程序不会以可预测的方式运行。有关更多详细信息,请参阅this SO post on undefined behavior(它包含一些C ++,但大多数想法都相同)。来自POSIX specs on vfork

  

vfork()函数与fork(2)具有相同的效果,除了   如果由vfork()创建的进程也未定义行为   修改除用于存储的pid_t类型的变量之外的任何数据   来自vfork()的返回值,或者从其中返回的函数返回   vfork()被调用,或者在成功之前调用任何其他函数   调用_exit(2)或exec(3)函数族之一。

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

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

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