首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >vfork()调用SYS_vfork,而fork()调用SYS_clone?

vfork()调用SYS_vfork,而fork()调用SYS_clone?
EN

Unix & Linux用户
提问于 2018-03-26 21:52:45
回答 2查看 1.2K关注 0票数 1

在由gcc编译的两个程序(版本5.4.0)上运行D1(版本5.4.0),一个调用vfork(),另一个调用fork()之后,我发现vfork()调用SYS_vfork,而fork()调用SYS_clone. 时,在任何地方都找不到有关这个特定行为的任何信息(一些来源说,每个fork()vfork()clone()都由相应的sys_调用实现,而其他来源则说所有三个调用都是使用sys_clone实现的)。

源代码:

代码语言:javascript
复制
#include
main()
{
        int pid;
        pid=vfork();
}

来自ltrace -S的输出:

代码语言:javascript
复制
...
__libc_start_main([some stuff here] 
vfork([more stuff] 
SYS_vfork([more stuff])
--- SIGCHLD (Child exited) ---

为什么libc在vfork()中使用SYS_vfork,而不使用SYS_fork来实现fork()呢?我读过托马斯·尼曼的回答内核中的哪个文件指定叉(),vfork()…使用sys_克隆()系统调用的文章,其中说:

然后,vfork()通过一个单独的CLONE_VFORK标志实现,这将导致父进程休眠,直到子进程通过信号唤醒它。子线程将是父名称空间中唯一的执行线程,直到它调用exec()或退出为止。不允许孩子在记忆中写字。相应的clone()调用如下:clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

这似乎与我观察到的ltrace -S输出不一致。

是我搞砸了什么,还是滑头编写人员故意选择使用vfork()而不是SYS_clone来实现?这被认为是在任何时候都可以改变的东西,还是我们可以依赖的东西?

EN

回答 2

Unix & Linux用户

回答已采纳

发布于 2018-03-26 22:59:37

是我搞砸了什么,还是glibc作者故意选择使用SYS_vfork而不是SYS_clone来实现vfork()是有原因的?

从历史上看,我认为这更有可能是vfork不需要更改的结果。vforkfork最初都使用等效的系统调用。当NPTL线程被实现时,这个fork实现改为使用clone,因为C库需要重置线程id.vfork不需要担心线程,因为它只适合与execve一起使用(这无论如何都会重置所有的状态),所以它没有受到任何影响。

NPTL设计论文解释了为什么当线程易于使用时,fork系统调用不足以实现fork库调用:

要在没有内存泄漏的情况下实现fork函数,除了调用fork的线程之外,用于堆栈和所有线程的其他内部信息的内存必须被回收。在这种情况下,内核是无能为力的。

这被认为是在任何时候都可以改变的东西,还是我们可以依赖的东西?

由于您使用C库来分叉,所以只能依赖C库提供API中记录的行为;您不能依赖特定的实现。您不应该依赖vfork(3)使用vfork(2)系统调用而不是clone(2),也不应该依赖使用clone(2)而不是fork(2)fork(3)。请注意,所使用的系统调用可能因体系结构而异.

如果您确实需要依赖特定的系统调用,则应该直接使用这些调用,并放弃C库包装器。

票数 5
EN

Unix & Linux用户

发布于 2018-03-26 22:50:57

man 2 fork

自2.3.3版本以来,C库/内核之间的差异,而不是调用内核的叉()系统调用,而是作为NPTL线程实现的一部分提供的glibc叉()包装器调用具有与传统系统调用相同效果的标志的克隆(2)。(对fork()的调用等价于对克隆(2)的调用,将标志指定为仅为SIGCHLD)。glibc包装器调用使用pthread_atfork(3)建立的任何分叉处理程序。

票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/433702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档