一尘不染

如何为Linux上的clone()系统调用映射堆栈?

linux

Linux上的clone()系统调用采用一个指向堆栈的参数,供新创建的线程使用。这样做的明显方法是简单地分配一些空间并传递该空间,但随后必须确保已分配了该线程将使用的尽可能多的堆栈空间(很难预测)。

我记得在使用pthreads时不必这样做,所以我很好奇它做了什么。我遇到了一个网站该网站解释说:“
Linux
pthreads实现使用的最佳解决方案是使用mmap分配内存,并使用标志指定使用时分配的内存区域。这样,就可以为根据需要将其放入堆栈,如果系统无法分配额外的内存,则会发生分段冲突。”

我听说过mmap的唯一使用上下文是将文件映射到内存,并且确实要阅读mmap手册页,它需要一个文件描述符。如何将其用于分配动态长度堆栈以提供给clone()?该网站只是疯狂的吗?;)

在这两种情况下,内核是否都不需要知道如何为新堆栈查找空闲的内存束,因为在用户启动新进程时,它总是必须做的事情吗?如果内核已经可以弄清楚为什么还要首先指定堆栈指针呢?


阅读 494

收藏
2020-06-07

共1个答案

一尘不染

约瑟夫,回答您的最后一个问题:

当用户创建“常规”新进程时,将由fork()完成。在这种情况下,内核根本不必担心创建新堆栈,因为新过程是旧堆栈的完全复制,一直到堆栈。

如果用户使用exec()替换当前正在运行的进程,则内核确实需要创建一个新的堆栈-
但是在这种情况下,这很容易,因为它是从空白开始的。exec()擦除进程的内存空间并重新初始化它,因此内核说“ exec()之后,堆栈始终在此处存在”。

但是,如果使用clone(),则可以说新进程将与旧进程(CLONE_VM)共享一个内存空间。在这种情况下,内核无法像在调用进程中那样离开堆栈(就像fork()一样),因为那样我们的两个进程将在彼此的堆栈上踩踏。内核也不能仅仅将其放在默认位置(就像exec()一样),因为该位置已经在此内存空间中占用了。唯一的解决方案是允许调用进程为其找到位置,这就是它的作用。

2020-06-07