gpt4 book ai didi

c - 在 vfork 中, child 被重复创建

转载 作者:太空宇宙 更新时间:2023-11-04 00:48:48 25 4
gpt4 key购买 nike

任何人都可以解释以下代码:

#include<stdio.h>
#include<stdlib.h>
main()
{
int a=1;
int pid;
if((pid = vfork()) == 0)
{
printf("This is child . %d\n", getpid() );
a=2;
}
else
{
printf("%d\t%d\n",getpid(),a);
sleep(1);
}
}

在上面的代码中,子进程被重复创建。谁能帮我理解其中的逻辑?

最佳答案

阅读vfork 的手册页。特别是它告诉您可以在 child 身上做什么的部分。您不能在 child 中调用 getpid。您不能在 child 中调用 printf。不允许设置变量 a。不允许从子进程中调用 vfork 的函数返回。你做了所有这些事情,因此代码做了一些意想不到的事情。不幸的是,意外的事情并没有崩溃。

您只能在 vfork:ed 子进程中调用 _exitexec* 函数之一。没有别的。

vfork 系统调用是 fork 非常昂贵的时代的优化 hack。那么在子进程调用 exec*_exit 之前,它是如何暂停父进程并在子进程中使用父进程地址空间(这可能是也可能不是真的,具体取决于操作系统) 。子进程所做的任何内存写入都会覆盖父进程中的内存。调用函数将以父进程不期望的方式覆盖内存。从调用 vfork 的函数返回肯定会覆盖父级期望完整的状态(比如返回地址和保存的堆栈指针)。调用 printf 将覆盖父级不希望被覆盖的 stdio 缓冲区,等等。

这可能是为什么在您的情况下,在所有计算机都具有确定性之后,父项在子项退出后再次调用自身的原因。如果您分析调用 main 的 crt 代码、libc 中的各种 atexit 处理程序和其他清理程序,您可能会确切地弄清楚在堆栈上的正确位置写入什么会使父级混淆并在系统调用返回。反汇编代码并开始吧。或者,您可以在该网站上搜索有关 vfork 的许多其他问题,并注意到它们都遵循相同的主题:“当我做某事时,为什么 vfork 会做一些意想不到的事情文档告诉我不要这样做?”。它这样做是因为它是未定义的行为,并且未定义行为的行为方式是未定义的。在您的情况下,覆盖父级不希望覆盖的内存恰好使父级再次调用自身。在其他情况下,我看到它使 printf 打印两次。在其他情况下,没有发生任何不好的事情。在其他情况下,程序会崩溃。

关于c - 在 vfork 中, child 被重复创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27374974/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com