这是真的,叉()()内部调用克隆? [英] Is it true that fork() calls clone() internally?

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

问题描述

我看了 的是的clone()系统调用用于在Linux中创建一个线程。现在的clone()是这样的,一个语法需要起动程序/功能的地址将被传递给它。

I read here that 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.

但在这里这个页写入了叉()通话的clone()内部。所以我的问题是怎么做的fork()的由创建子进程开始运行)code这是继叉的部分(通话,即它是如何不需要的功能为出发点?

But here on this 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.

感谢

推荐答案

有关这样的问题,务必阅读源$ C ​​$ C。

For questions like this, always read the source code.

从的glibc的 NPTL / sysdeps / UNIX / SYSV / Linux的/ fork.c (<一个href=\"https://github.com/lattera/glibc/blob/416bf844227d37b043b16be28c9523eeaecd3de3/nptl/sysdeps/unix/sysv/linux/fork.c\">GitHub) ( NPTL =原生POSIX线程对于Linux),我们可以找到的实施叉(),这绝对是<强>不可以系统调用,我们可以看到,神奇的 ARCH_FORK 宏,它被定义为内联调用克隆内发生( ) NPTL / sysdeps / UNIX / SYSV / Linux的/ x86_64的/ fork.c (<一个href=\"https://github.com/lattera/glibc/blob/416bf844227d37b043b16be28c9523eeaecd3de3/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c\">GitHub).别急,无功能或堆栈指针传递给),这个版本的的克隆(!那么,什么是怎么回事?

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?

让我们来看看的clone()的glibc中实现,那么。它在 sysdeps / UNIX / SYSV / Linux的/ x86_64的/ clone.S (<一个href=\"https://github.com/lattera/glibc/blob/416bf844227d37b043b16be28c9523eeaecd3de3/sysdeps/unix/sysv/linux/x86_64/clone.S\">GitHub).你可以看到,它的作用是它可以节省孩子的堆栈上的函数指针,调用系统调用克隆,然后新的进程将读取弹出功能关闭栈,然后调用它。

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.

因此​​,它的工作原理是这样的:

So it works like this:

clone(void (*fn)(void *), void *stack_pointer)
{
    push fn onto stack_pointer
    syscall_clone()
    if (child) {
        pop fn off of stack
        fn();
        exit();
    }
}

叉()是...

fork()
{
    ...
    syscall_clone();
    ...
}

摘要

实际的clone()系统调用并不需要一个函数的参数,它只是从返回点继续,就像叉()。因此,无论在的clone()叉()的库函数的周围包装的的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()系统调用更紧密地对应于叉(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.

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

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