我在这里读到,clone()
系统调用用于在Linux中创建线程。现在,语法的clone()
是这样的,就需要启动程序/函数地址传递给它。
但是在此页面上,此内容是内部fork()
调用的clone()
。所以我的问题是,由子程序创建的子进程如何fork()
开始运行fork()
调用后的代码部分,即它如何不需要以函数为起点?
如果我提供的链接信息不正确,请引导我找到一些更好的链接/资源。
谢谢
对于此类问题,请始终阅读源代码。
从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, ...
/* 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()
包装函数和它所基于的基础系统调用。正文描述了包装函数;原始系统调用的差异将在本页尾进行描述。
最后,
原始
clone()
系统调用更紧密地对应fork(2)
于子调用中的子进程继续执行。这样,将clone()
省略包装函数的fn和arg参数。此外,参数顺序也会改变。
问题内容: 在 UNIX到Windows移植词典HPC 页的叉()这是写 没有与Unix fork()或vfork()等效的Windows API。用于基于Unix的应用程序的Microsoft子系统(SUA或Interix)是一个Unix环境,具有正确实现的fork()和vfork()。 在页面的后面还有使用标准Win32 API 函数的示例源代码。 我糊涂了。 该示例不应该使用fork()来说
问题内容: 我一直想在Google上找到这四个之间的区别,我希望这方面会有大量的信息,但是这四个调用之间确实没有任何可靠的比较。 我着手尝试汇编一下这些系统调用之间的区别的基本概况,这就是我得到的。所有这些信息是否正确/我是否缺少任何重要信息? :fork调用基本上是对当前过程进行复制,几乎在所有方面都相同(例如,并非在某些实现中都复制了所有内容,例如,在某些实现中资源有限,但其想法是创建尽可能近
问题内容: 我是这方面的初学者。 我研究过,,和并行线程。 我注意到,这将创建一个线程,这比使用创建新进程要少。另外,线程将与父进程共享文件描述符,内存等。 但是,当是和比并行线程更好?您能举个真实的例子给我解释一下吗? 提前致谢。 问题答案: (和公司)的优缺点是,他们创建了一个新流程,该流程是现有流程的克隆。 正如您所指出的那样,这是一个弱点,因为创建新流程会产生相当大的开销。这也意味着进程之
这个包的主要用途就是在 API 内部执行请求。它允许你在可用的 API 基础上构建你的应用。内部请求也可以返回原始数据,而不是原始响应对象,这意味着你可以获得与之相关的所有语法糖。 我们需要构建一个分发器实例来发起内部请求。 $dispatcher = app('Dingo\Api\Dispatcher'); 我们现在可以用标准的 HTTP 进行内部请求. Route::get('/', func
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); if (pid < 0) { exit(1); } else if (pid > 0
问题内容: 假设我有一个Python函数和。旨在以递归方式调用自身。不应递归调用。有没有办法确定是否已递归调用它? 问题答案: 为此使用追溯模块: 因此,如果堆栈中的任何条目指示从调用了代码,则该调用是(间接)递归的。该方法使您可以轻松访问此数据。下面的示例中的语句仅计算函数名称的完全匹配数。为了使它更漂亮(感谢agf的想法),您可以将其变成装饰器: