vfork() 调用后退出和返回之间的区别
我有一个具有未定义行为的程序( vfork() 使用不当):
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main ( int argc, char *argv[] )
{
pid_t pid;
printf("___________befor fork______________.\n");
if((pid=vfork()) < 0)
perror("fork");
else if(pid > 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()
函数之后的子级中使用 return
。 但我不明白为什么父级在 return
调用后没有结束?
谢谢。
I have a program with undefined behavior ( vfork() is used inappropriately ):
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main ( int argc, char *argv[] )
{
pid_t pid;
printf("___________befor fork______________.\n");
if((pid=vfork()) < 0)
perror("fork");
else if(pid > 0)
printf("parent\n");
else
printf("child\n");
printf("pid: %d, ppid: %d\n", getpid(), getppid());
//exit(0);
return 0;
}
If I use exit(0)
function instead return - output is:
___________befor fork______________.
child
pid: 4370, ppid: 4369
parent
pid: 4369, ppid: 2924
If I use return 0
- I get infinite output like this:
___________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 ...
I know that you can not use return
in the child after the vfork()
function.
But I don't understand why the parent does not end after return
call?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从子级中的函数返回是无效的,因为使用
vfork()
父级和子级共享相同的堆栈,并且在子级中返回会弄乱父级的堆栈帧。通常,对main()
的调用(在启动函数中)后面会调用exit()
或类似的函数,以便调用exit()<子级中的 /code> 将覆盖对
main()
的调用所使用的相同堆栈空间(并且仍在父级中使用)。因此,当子进程确实退出时,父进程将从 vfork() 返回,但堆栈上的返回地址可能会被破坏,因此它可以返回到任何地址或执行任何操作。另外,在子进程中,如果您不执行,则应该调用
_exit()
而不是exit()
。exit()
将刷新 stdio 输出缓冲区,但这些相同的缓冲区由父级管理,而_exit()
将只是结束进程。It is not valid to return from the function in the child, because with
vfork()
both the parent and child share the same stack and returning in the child will mess up the stack frame for the parent. Usually the call tomain()
(in the start function) is followed by a call toexit()
or similar, so that call toexit()
in the child will overwrite the same stack space that the call tomain()
was using (and is still using in the parent). So when the child does exit, the parent will return fromvfork()
but the return address on the stack will likely be clobbered so it could return to any address or do anything at all.Also, in the child, if you do not exec you should call
_exit()
rather thanexit()
.exit()
will flush the stdio output buffers but those same buffers are being managed by the parent, whereas_exit()
will just end the process.通过返回子进程,您将导致未定义的行为,因此任何事情都可能发生。
看起来您的父进程工作正常,但子进程没有退出,而是重新启动
main
函数。By returning in your child process you are causing undefined behavior, so anything can really happen.
It looks like you parent process works fine, but the child process, instead of exiting, restarts
main
function.你可以在 kernel.org 中看到 vfork 的定义: http://www.kernel.org/doc/man-pages/online/pages/man2/vfork.2.html 。这是一个很好的解释。
you can see the definition of vfork in the kernel.org : http://www.kernel.org/doc/man-pages/online/pages/man2/vfork.2.html . it is a good explanation.
当前的 POSIX 标准根本不支持
vfork()
。在旧的(1997 年左右)POSIX 标准中,
vfork( )
说:您的代码没有调用
exec
系列函数或_exit()
,因此您调用了未定义的行为,并且发生的任何事情都是合法的。您刚刚演示了为什么使用
vfork()
通常不明智。 IMNSHO,它与 gets() 属于同一阵营;我知道它存在,但我永远不会自愿使用它,并且我会非常高兴实现如下:The current POSIX standard does not support
vfork()
at all.In the old (1997-ish) POSIX standard, the page for
vfork()
said:Your code is not calling either an
exec
family function or_exit()
, so you invoke undefined behaviour, and anything that happens is legitimate.You've just demonstrated why it is not usually sensible to use
vfork()
. IMNSHO, it is in the same camp asgets()
; I know it exists but I would never use it voluntarily, and I'd be perfectly happy for the implementations to be: