Linux 进程虚拟地址空间中其他线程的堆栈在哪里?

Linux 进程虚拟地址空间中其他线程的堆栈在哪里?,linux,assembly,process,x86,Linux,Assembly,Process,X86,下图显示了进程的各个部分在进程的虚拟地址空间中的布局(在Linux中): 您可以看到只有一个堆栈部分(因为我假设这个进程只有一个线程) 但是,如果这个进程有另一个线程,那么第二个线程的堆栈将位于哪里呢?它是否位于第一个堆栈的正下方?据我所知,用于处理堆栈的空间被划分为更小的部分,每个部分由给定的线程使用。中间还有一些保护页,以防止意外粉碎。是的,堆栈比其他堆栈低一个…新线程的堆栈空间是由具有的父线程创建的。因此,它们位于“内存映射段”中,如图所示。它可以在大型malloc()可以去的任何地方结

下图显示了进程的各个部分在进程的虚拟地址空间中的布局(在Linux中):

您可以看到只有一个堆栈部分(因为我假设这个进程只有一个线程)


但是,如果这个进程有另一个线程,那么第二个线程的堆栈将位于哪里呢?它是否位于第一个堆栈的正下方?

据我所知,用于处理堆栈的空间被划分为更小的部分,每个部分由给定的线程使用。中间还有一些保护页,以防止意外粉碎。是的,堆栈比其他堆栈低一个…

新线程的堆栈空间是由具有的父线程创建的。因此,它们位于“内存映射段”中,如图所示。它可以在大型
malloc()
可以去的任何地方结束。(glibc
malloc(3)
使用
mmap(MAP\u匿名)
进行大型分配。)

MAP_STACK
目前是不可操作的,存在于某些未来架构需要特殊处理的情况下)

您传递一个指向新线程堆栈空间的指针,该堆栈空间实际创建了线程。(请尝试在多线程进程上使用
strace-f
)。另见

有关mmaping堆栈的更多详细信息,请参阅。e、 g.
MAP\u GROWSDOWN
不会阻止另一个
mmap()
从线程堆栈的正下方选择地址,因此您不能依靠它以主线程堆栈的方式动态增长一个小堆栈(内核保留地址空间,即使它尚未映射)

因此,即使
mmap(MAP\u GROWSDOWN)
是为分配堆栈而设计的


另外,请注意,内存映射图是针对32位内核的。64位内核不必为映射内核内存保留任何用户虚拟地址空间,因此在amd64内核上运行的32位进程可以使用全部4GB的虚拟地址空间。(除了默认情况下的低64k(sysctl
vm.mmap_min_addr=65536
),因此空指针取消引用实际上是错误的。)


相关的:


有关pthreads的堆栈大小的更多信息,请参阅
getrlimit(RLIMIT_STACK)
是主线程的堆栈大小。Linux pthreads也使用
RLIMIT_STACK
作为新线程的堆栈大小。

C标记不相关,C没有定义它们的概念。另请参阅。Qualys设法打破了逻辑内存区域之间的分离。他们可以使用一个内存区域覆盖另一个区域中的对象。Linux尤其易受攻击(运行的系统除外)。另请参见OSS安全邮件列表。这意味着
ulimit-s
(堆栈大小)在进程中的所有线程之间共享。对于非常高的线程数来说,这似乎不太可能。我同意,这些都是旧的内存,自:-)以来情况可能发生了很大的变化。有关pthreads的堆栈大小的更多信息,请参阅
getrlimit(RLIMIT_STACK)
是主线程的堆栈大小。它不是为多个线程分割的;使用Linux pthreads,每个线程都有自己的堆栈大小
RLIMIT\u stack