fork() 在内部调用 clone() 是真的吗? [英] Is it true that fork() calls clone() internally?

查看:20
本文介绍了fork() 在内部调用 clone() 是真的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了Linux 内核开发,第二版"的第 3 章.Robert Love (ISBN:0-672-32720-1) 指出 clone 系统调用用于在 Linux 中创建线程.现在是 clone语法是这样的,因此需要将起始例程/函数地址传递给它.

I read in the 3rd chapter of the "Linux Kernel Development, Second Edition" by Robert Love (ISBN:0-672-32720-1) that the clone system call is used to create a thread in Linux. Now the syntax of clone is such that a starting routine/function address is needed to be passed to it.

然后在同一页面上写到 fork 在内部调用 clone.所以我的问题是,由 fork 创建的子进程如何开始运行 fork 调用之后的代码部分,即它如何不需要函数作为起点?

But then on the same page it is written that fork calls clone internally. So my question is, how do child process created by fork starts running the part of code which is after fork call, i.e. how does it not require a function as starting point?

如果我提供的链接信息不正确,请指导我找到更好的链接/资源.

If the links I provided have incorrect info, then please guide me to some better links/resources.

推荐答案

此类问题,请务必阅读源代码.

For questions like this, always read the source code.

来自 glibc 的 nptl/sysdeps/unix/sysv/linux/fork.c (GitHub) (nptl = Linux 的本地 Posix 线程) 我们可以找到 fork() 的实现,这绝对是不是系统调用,我们可以看到魔术发生在 ARCH_FORK 宏内部,该宏被定义为对 clone()nptl/sysdeps/unix/sysv/linux/x86_64/fork.c 中的代码> (GitHub).但是等等,没有函数或堆栈指针被传递给这个版本的 clone()!那么,这里发生了什么?

From glibc's nptl/sysdeps/unix/sysv/linux/fork.c (GitHub) (nptl = native Posix threads for Linux) we can find the implementation of fork(), which is definitely not a syscall, we can see that the magic happens inside the ARCH_FORK macro, which is defined as an inline call to clone() in nptl/sysdeps/unix/sysv/linux/x86_64/fork.c (GitHub). But wait, no function or stack pointer is passed to this version of clone()! So, what is going on here?

接下来看看glibc中clone()的实现.它在 sysdeps/unix/sysv/linux/x86_64/clone.S (GitHub).可以看到它的作用是将函数指针保存在子栈中,调用clone syscall,然后新进程会读取栈中的函数然后调用.

Let's look at the implementation of clone() in glibc, then. It's in sysdeps/unix/sysv/linux/x86_64/clone.S (GitHub). You can see that what it does is it saves the function pointer on the child's stack, calls the clone syscall, and then the new process will read pop the function off the stack and then call it.

所以它是这样工作的:

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() 系统调用不接受函数参数,它只是从返回点继续,就像fork() 一样.所以 clone()fork() 库函数 都是 clone() 系统调用的包装器.

Summary

The actual clone() syscall does not take a function argument, it just continues from the return point, just like fork(). So both the clone() and fork() library functions are wrappers around the clone() syscall.

我的手册副本更直接地说明了 clone() 既是库函数又是系统调用的事实.但是,我确实发现 clone() 出现在第 2 节而不是第 2 节和第 3 节中,这有点误导.从手册页:

My copy of the manual is somewhat more upfront about the fact that clone() is both a library function and a system call. However, I do find it somewhat misleading that clone() is found in section 2, rather than both section 2 and section 3. From the man page:

#include <sched.h>

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

/* Prototype for the raw system call */

long clone(unsigned long flags, void *child_stack,
          void *ptid, void *ctid,
          struct pt_regs *regs);

还有,

本页描述了 glibc clone() 包装函数和它所基于的底层系统调用.正文描述包装函数;原始系统调用的区别是在本页末尾进行了描述.

This page describes both the glibc clone() wrapper function and the underlying system call on which it is based. The main text describes the wrapper function; the differences for the raw system call are described toward the end of this page.

最后,

原始的 clone() 系统调用更接近于 fork(2)子进程中的执行从调用点继续.像这样,clone() 包装函数的 fn 和 arg 参数被省略.此外,参数顺序也会发生变化.

The raw clone() system call corresponds more closely to fork(2) in that execution in the child continues from the point of the call. As such, the fn and arg arguments of the clone() wrapper function are omitted. Furthermore, the argument order changes.

这篇关于fork() 在内部调用 clone() 是真的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆