# vfork 挂掉的一个问题

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
int var;
var = 88;
if ((pid = vfork()) < 0) {
printf("vfork error");
exit(-1);
} else if (pid == 0) { /* 子进程 */
var++;
return 0;
}
printf("pid=%d, glob=%d, var=%d\n", getpid(), glob, var);
return 0;
}


#### 基础知识

• fork 是 创建一个子进程，并把父进程的内存数据copy到子进程中。
• vfork是 创建一个子进程，并和父进程的内存数据share一起用。

1）保证子进程先执行。
2）当子进程调用exit()或exec()后，父进程往下执行。

Historic Description

Under Linux, fork(2) is implemented using copy-on-write pages, so the only penalty incurred by fork(2) is the time and memory required to duplicate the parent’s page tables, and to create a unique task structure for the child. However, in the bad old days a fork(2) would require making a complete copy of the caller’s data space, often needlessly, since usually immediately afterwards an exec(3) is done. Thus, for greater efficiency, BSD introduced the vfork() system call, which did not fully copy the address space of the parent process, but borrowed the parent’s memory and thread of control until a call to execve(2) or an exit occurred. The parent process was suspended while the child was using its resources. The use of vfork() was tricky: for example, not modifying data in the parent process depended on knowing which variables are held in a register.

#### 为什么return会挂掉，exit()不会？

1）子进程的main() 函数 return了，于是程序的函数栈发生了变化。

2）而main()函数return后，通常会调用 exit()或相似的函数（如：_exit()，exitgroup()）

3）这时，父进程收到子进程exit()，开始从vfork返回，但是尼玛，老子的栈都被你子进程给return干废掉了，你让我怎么执行？（注：栈会返回一个诡异一个栈地址，对于某些内核版本的实现，直接报“栈错误”就给跪了，然而，对于某些内核版本的实现，于是有可能会再次调用main()，于是进入了一个无限循环的结果，直到vfork 调用返回 error）

#### 关于fork的优化

“ It is rather unfortunate that Linux revived this specter from the past. The BSD man page states: “This system call will be eliminated when proper system sharing mechanisms are implemented. Users should not depend on the memory sharing semantics of vfork() as it will, in that case, be made synonymous to fork(2).””

（全文完）

（转载本站文章请注明作者和出处 酷 壳 – CoolShell.cn ，请勿用于任何商业用途）

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——

11-26 69

08-24 395
03-04 28
04-05 28
05-11 54
11-18 239
12-08
12-31
12-18 49万+
05-20