2

我正在做一些自学的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 a输出line b

a部分的输出是:

Value of v is 79525.
Sum is 13.

b部分的输出是:

Value of v is 79517.
Sum is 16.

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

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

根据这篇文章

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

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

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

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

4

1 回答 1

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(这也是无效的,因为它应该调用_exita很可能等于 10 并且b很可能等于 6在 parent 中。因此,总和为 16,如 b 部分所示。我说很可能是因为如前所述,该程序具有未定义的行为。

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

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

于 2015-08-02T20:08:02.190 回答