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

发布于 2024-12-09 01:27:47 字数 1150 浏览 0 评论 0原文

我有一个具有未定义行为的程序( 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时常饿 2024-12-16 01:27:47

从子级中的函数返回是无效的,因为使用 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 to main() (in the start function) is followed by a call to exit() or similar, so that call to exit() in the child will overwrite the same stack space that the call to main() was using (and is still using in the parent). So when the child does exit, the parent will return from vfork() 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 than exit(). exit() will flush the stdio output buffers but those same buffers are being managed by the parent, whereas _exit() will just end the process.

盛装女皇 2024-12-16 01:27:47

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

看起来您的父进程工作正常,但子进程没有退出,而是重新启动 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.

指尖上的星空 2024-12-16 01:27:47

你可以在 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.

海未深 2024-12-16 01:27:47

当前的 POSIX 标准根本不支持 vfork()
在旧的(1997 年左右)POSIX 标准中,vfork( ) 说:

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

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

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

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

The current POSIX standard does not support vfork() at all.
In the old (1997-ish) POSIX standard, the page for vfork() said:

The vfork() function has the same effect as fork(), except that the behaviour is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions.

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 as gets(); I know it exists but I would never use it voluntarily, and I'd be perfectly happy for the implementations to be:

pid_t vfork(void) { abort(); }
char *gets(char *buffer) { abort(); }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文