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

时间:2017-07-01 07:36:22

标签: linux assembly process x86

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

enter image description here

你可以看到只有一个堆栈部分(因为这个过程只有一个我假设的线程)。

但是,如果这个进程有另一个线程,那么第二个线程的堆栈将位于何处?它会位于第一个堆栈的正下方吗?

2 个答案:

答案 0 :(得分:6)

新线程的堆栈空间由父线程mmap(MAP_ANONYMOUS|MAP_STACK)创建。因此,它们位于“内存映射段”中,因为您的图表标记了它。它最终会导致大malloc()的任何地方。 (glibc malloc(3)使用mmap(MAP_ANONYMOUS)进行大量分配。)

MAP_STACK目前是无操作的,如果将来某些架构需要特殊处理,则存在。)

将指向新线程堆栈空间的指针传递给实际创建线程的the clone(2) system call。 (有时在多线程进程中尝试使用strace -f)。另请参阅this blog post about creating a thread using raw Linux syscalls

有关mmaping堆栈的更多详细信息,请参阅this answer on a related question。例如MAP_GROWSDOWN不会阻止另一个mmap()选择线程堆栈正下方的地址,因此您无法依赖它来以主线程堆栈的方式动态增长小堆栈(其中内核保留地址空间,即使它尚未映射)。

所以尽管mmap(MAP_GROWSDOWN)是为分配堆栈而设计的,it's so bad that Ulrich Drepper proposed removing it in 2.6.29

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

相关:

有关pthreads的堆栈大小的更多信息,请参阅Relation between stack limit and threadsgetrlimit(RLIMIT_STACK)是主线​​程的堆栈大小。 Linux pthreads也使用RLIMIT_STACK作为新线程的堆栈大小。

答案 1 :(得分:-2)

据我所知,专用于进程堆栈的空间被分成较小的部分,每个部分由给定的线程使用。中间还有一些防护页面,以防止意外粉碎。是的,堆栈低于其他堆栈......