c - 如果 vfork() 调用 exec 族,为什么它不是未定义的?

标签 c linux system-calls

根据 vfork() 手册页,如果 vfork() 在调用 _exit 或 exec 之前修改除 pid_t 之外的任何数据,则行为未定义系统调用系列。

由此我了解到,如果vfork()创建的子进程调用exec(),那么它可以修改任何数据,而且行为仍然不是未定义。

我的问题是:

  1. 众所周知,子进程共享父地址空间,那么如果子进程使用 exec 覆盖、 self 和父镜像,行为不是未定义的,怎么会这样呢?

  2. 如果子调用 exec 然后它返回,父会发生什么? parent 是否开始使用 child 使用 exec 创建的新副本?

最佳答案

exec 调用用一个全新的地址空间替换了 child 的整个地址空间。任何共享地址空间都将被调用完全替换。

vfork 函数仅作为优化存在。对于某些操作系统,fork 非常昂贵,因为子进程可能会修改映射到内存中的任何页面,因此必须修改每个页面以在写入时复制(或者,最初,实际复制!),以免修改父进程的相应页面页。一个非常常见的序列是 fork 紧接着是 exec ,迫使这些系统重新映射所有页面只是为了在一瞬间将它们全部丢弃。 vfork 允许您在假设您无论如何都不会使用它们的情况下,将映射保留在子进程中的未定义状态,而不是修改所有映射的麻烦。

因此,在 vfork 之后做某些事情可能会造成困惑。但是只要你调用 exec ,所有未定义的映射都会消失。

在实践中,操作系统处理 vfork 有两种方式之一:对于将所有映射更改为写入时复制成本低廉或尚未实现 vfork 优化的操作系统,vforkfork 相同。对于确实使用 vfork 优化的操作系统,vfork 让父子完全共享大部分页面,如果子修改它们(它们在父中修改),就会导致不好的事情发生。

所以对你的问题的简短回答是,如果 vfork 是这样设计的,它就不能用于其唯一的预期目的。

关于c - 如果 vfork() 调用 exec 族,为什么它不是未定义的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7058244/

相关文章:

c - 我只是无法理解这么简单的程序。请帮忙。下面是程序和我的理解的代表

c - 虚拟时间已过

c - 是否有描述 C 函数名称 "stand for"的文档(不是它们的作用——而是缩写名称的含义)?

linux - 如何删除 setgid (linux/unix)?

linux - 尝试按照此处的答案在我的终端中显示 git 分支,但它似乎不起作用

java - strace: `dup2(A, B); close(B)` 有什么意义吗?

c - 为什么 ANSI C 没有 namespace ?

用 C 语言将 IEEE 754 float 转换回十进制?

c - 如何在迭代字符串指针后从 void 函数获取指针

linux - SOX 的采样率误差