父线程使用来创建新线程的堆栈空间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用作新线程的堆栈大小。