对于此类问题,请始终阅读源代码。
从glibc
nptl/sysdeps/unix/sysv/linux/fork.c(GitHub)(
nptl=
Linux的本地Posix线程)中,我们可以找到的实现
fork(),它绝对 不是
syscall,我们可以看到魔术发生在
ARCH_FORK宏内部,该宏定义为
clone()in
nptl/sysdeps/unix/sysv/linux/x86_64/fork.c(GitHub)的内联调用。但是,等等,没有函数或堆栈指针传递给此版本的
clone()!那么,这是怎么回事?
clone()接下来,让我们看一下glibc
中的实现。在
sysdeps/unix/sysv/linux/x86_64/clone.S(GitHub)中。您可以看到它的作用是将函数指针保存在孩子的堆栈上,调用clone
syscall,然后新进程将读取从堆栈弹出的函数,然后对其进行调用。
所以它是这样的:
clone(void (*fn)(void *), void *stack_pointer){ push fn onto stack_pointer syscall_clone() if (child) { pop fn off of stack fn(); exit(); }}而且
fork()是…
fork(){ ... syscall_clone(); ...}摘要
实际的
clone()syscall不接受函数参数,它只是从返回点继续,就像
fork()。因此
clone()和和
fork()库函数
都是
clone()syscall的包装器。
文献资料
我的手册副本是关于
clone()库函数和系统调用的事实的一些预告。但是,我确实
clone()在第2节中找到了误导,而不是在第2节和第3节中都发现了这种误解。
#include <sched.h>int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... );long clone(unsigned long flags, void *child_stack, void *ptid, void *ctid, struct pt_regs *regs);
和,
该页面同时描述了glibc
clone()包装函数和它所基于的基础系统调用。正文描述了包装函数;原始系统调用的差异将在本页尾进行描述。
最后,
原始
clone()系统调用更紧密地对应fork(2)于子调用中的子进程继续执行。这样,将clone()省略包装函数的fn和arg参数。此外,参数顺序也会改变。



