vfork()调用后退出和返回之间的区别

我有一个程序具有未定义的行为(vfork()使用不当):

#include  #include  #include  int main ( int argc, char *argv[] ) { pid_t pid; printf("___________befor fork______________.\n"); if((pid=vfork())  0) printf("parent\n"); else printf("child\n"); printf("pid: %d, ppid: %d\n", getpid(), getppid()); //exit(0); return 0; } 

如果我使用exit(0)函数而不是return – 输出是:

 ___________befor fork______________. child pid: 4370, ppid: 4369 parent pid: 4369, ppid: 2924 

如果我使用return 0 – 我得到无限输出:

 ___________befor fork______________. child pid: 4455, ppid: 4454 parent pid: 4454, ppid: 2924 ___________befor fork______________. child pid: 4456, ppid: 4454 parent pid: 4454, ppid: 2924 ___________befor fork______________. child pid: 4457, ppid: 4454 parent pid: 4454, ppid: 2924 and so on ... 

我知道你不能在vfork()函数之后使用子vfork()中的return 。 但我不明白为什么父母在回电后没有结束?

谢谢。

vfork()返回是无效的,因为使用vfork() ,父和子共享相同的堆栈,并且在子级中返回将弄乱父级的堆栈帧。 通常调用main() (在start函数中)之后是对exit()或类似的调用,因此对子节点中的exit()调用将覆盖对main()的调用所使用的相同堆栈空间(并且仍在父母中使用)。 因此当子进程退出时,父vfork()将从vfork()返回,但堆栈上的返回地址可能会被破坏,因此它可以返回任何地址或做任何事情。

另外,在孩子中,如果你不执行,你应该调用_exit()而不是exit()exit()将刷新stdio输出缓冲区,但那些相同的缓冲区由父级管理,而_exit()将只结束进程。

通过在子进程中返回,您将导致未定义的行为,因此任何事情都可能发生。

看起来你的父进程工作正常,但子进程,而不是退出,重新启动main函数。

目前的POSIX标准根本不支持vfork() 。 在旧的(1997-ish)POSIX标准中, vfork()的页面说:

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

您的代码不会调用exec系列函数或_exit() ,因此您调用未定义的行为,并且发生的任何事情都是合法的。

您刚刚演示了为什么使用vfork()通常不合理。 IMNSHO,它与gets()在同一个阵营; 我知道它存在,但我永远不会自愿使用它,我会非常高兴实现:

 pid_t vfork(void) { abort(); } char *gets(char *buffer) { abort(); } 

你可以在kernel.org中看到vfork的定义: http ://www.kernel.org/doc/man-pages/online/pages/man2/vfork.2.html。 这是一个很好的解释。