进程虚拟地址空间中其他线程的堆栈在哪里? [英] Where are the stacks for the other threads located in a process virtual address space?

查看:346
本文介绍了进程虚拟地址空间中其他线程的堆栈在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following image shows where the sections of a process are laid out in the process's virtual address space (in Linux):

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

You can see that there is only one stack section (since this process only has one thread I assume).

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

But what if this process has another thread, where will the stack for this second thread be located? will it be located immediately below the first stack?

推荐答案

父线程使用malloc()可能出现的任何位置. (glibc malloc(3)使用mmap(MAP_ANONYMOUS)进行大分配.)

Stack space for a new thread is created by the parent thread with mmap(MAP_ANONYMOUS|MAP_STACK). So they're in the "memory map segment", as your diagram labels it. It can end up anywhere that a large malloc() could go. (glibc malloc(3) uses mmap(MAP_ANONYMOUS) for large allocations.)

(MAP_STACK当前为空操作,并且在将来的某些体系结构需要特殊处理的情况下存在).

(MAP_STACK is currently a no-op, and exists in case some future architecture needs special handling).

您将指向新线程堆栈空间的指针传递到 系统调用实际创建线程. (有时尝试在多线程进程上使用strace -f).另请参见此博客文章,其中涉及使用原始Linux系统调用创建线程.

You pass a pointer to the new thread's stack space to the clone(2) system call which actually creates the thread. (Try using strace -f on a multi-threaded process sometime). See also this blog post about creating a thread using raw Linux syscalls.

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

See this answer on a related question for some more details about mmaping stacks. e.g. MAP_GROWSDOWN doesn't prevent another mmap() from picking the address right below the thread stack, so you can't depend on it to dynamically grow a small stack the way you can for the main thread's stack (where the kernel reserves the address space even though it's not mapped yet).

因此,即使mmap(MAP_GROWSDOWN)是为分配堆栈而设计的,但这很糟糕,Ulrich Drepper建议在2.6中将其删除.29 .

So even though mmap(MAP_GROWSDOWN) was designed for allocating stacks, 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指针取消引用确实会出错.)

Also, note that your memory-map diagram is for a 32-bit kernel. A 64-bit kernel doesn't have to reserve any user virtual-address space for mapping kernel memory, so a 32-bit process running on an amd64 kernel can use the full 4GB of virtual address space. (Except for the low 64k by default (sysctl vm.mmap_min_addr = 65536), so NULL-pointer dereference does actually fault.)

相关:

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

See Relation between stack limit and threads for more about stack-size for pthreads. getrlimit(RLIMIT_STACK) is the main thread's stack size. Linux pthreads uses RLIMIT_STACK as the stack size for new threads, too.

这篇关于进程虚拟地址空间中其他线程的堆栈在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆