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

Joh*_*ohn 4 linux x86 assembly process

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

在此处输入图片说明

您会看到只有一个堆栈部分(因为我假设该进程只有一个线程)。

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

Pet*_*des 7

父线程使用来创建新线程的堆栈空间mmap(MAP_ANONYMOUS|MAP_STACK)。因此它们就在“内存映射段”中,正如您的图表所标记的那样。它可能会终止于大公司malloc()可能去的任何地方。(glibc的malloc(3)用途mmap(MAP_ANONYMOUS)对于大的分配)。

MAP_STACK目前是禁止操作,并且在将来的某些架构需要特殊处理的情况下存在)。

您将指向新线程的堆栈空间的指针传递给实际创建线程clone(2)系统调用。(尝试strace -f在多线程进程上使用)。另请参阅有关使用原始Linux syscall创建线程的博客文章

有关映射映射的更多详细信息,请参见相关问题的答案。例如,MAP_GROWSDOWN它不会阻止另一个人mmap()在线程堆栈下方选择地址,因此您不能依靠它动态地扩展小堆栈,就像您为主线程的堆栈所用(内核保留地址空间,即使它是尚未映射)。

因此,即使mmap(MAP_GROWSDOWN)是为分配堆栈而设计的,也是如此,以至于Ulrich Drepper提议在2.6.29中删除它


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


有关:

有关pthread的堆栈大小的更多信息,请参见堆栈限制与线程之间的关系getrlimit(RLIMIT_STACK)是主线程的堆栈大小。Linux pthreads也RLIMIT_STACK用作新线程的堆栈大小。