【发布时间】:2015-08-02 19:50:28
【问题描述】:
我正在做一些自学的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);
}
第二部分:
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部分出现,sum是a和b的初始声明的总和,而在b部分,sum包括子进程内的总和。
我的问题是 - 为什么会这样?
据此post:
两者的基本区别在于,当一个新进程被 使用 vfork() 创建,父进程被暂时挂起,并且 子进程可能会借用父进程的地址空间。这 奇怪的事态一直持续到子进程 退出,或调用 execve(),此时父进程继续。
父进程的定义暂时中止对我来说没有多大意义。这是否意味着对于1b,程序会等到子进程完成运行(因此为什么子进程变量会被求和),然后父进程才会运行?
问题陈述还假设“内核维护的父进程的进程ID为2500,并且新进程是在子进程创建之前由操作系统创建的”。
根据这个定义,两个程序的v 的值是多少?
【问题讨论】:
-
"
vfork()函数应等效于fork(),除非vfork()[...] 创建的进程修改除类型变量之外的任何数据时行为未定义pid_t用于存储来自vfork()的返回值” - 这个问题是“我的代码的行为未定义,但它为什么会做这个特殊的 事情?”的另一个实例 -
在
vfork之后,父级被挂起,直到子级调用exec*函数或直到它_exits,以先发生者为准。在常规分叉中,您根本不会重写变量,因为每个进程都有自己的副本。 -
@PSkocik 谢谢你的回答。如果我理解正确,
fork()会生成一个单独的副本,这就是为什么a和b保留它们的初始化值并且不被写入。对于vfork(),子执行,这就是求和发生在子内部的原因。 -
如果你对
vfork感到好奇,它的目的是在fork/exec中使用它来启动一个新程序,但不复制原程序的内存。这在操作系统中很重要,因为操作系统必须复制内存页面而不是将它们标记为 COW。今天,它在配置为禁用内存过量使用的操作系统上仍然很重要。在没有过度使用的 Linux 上,使用 fork/exec 的 2 GB Java 进程将需要 2 GB 可用 RAM。 vfork/exec 不会。 -
调用系统函数:fork()或vfork()时,有三种结果。 1) 函数失败,在这种情况下返回 -1 2) 函数成功并且父进程正在执行(返回子进程的 pid) 3) 函数成功并且子进程正在执行(返回 0 的 pid) 调用时无论是这些功能,代码都应该检查所有三个条件,而不仅仅是“成功”条件。\