属于线程的堆栈与进程的堆栈有何不同
Posted
技术标签:
【中文标题】属于线程的堆栈与进程的堆栈有何不同【英文标题】:How is a stack belonging to a thread different from a stack of a process 【发布时间】:2012-03-30 17:24:53 【问题描述】:谁能告诉我这两种类型的堆栈有什么区别。
如果我看到 /proc/<pid>/map
和 proc/pid/task/<tid>
我看到的是同一张地图。有没有办法我们可以看到专门属于线程的堆栈(我的意思不是进程线程的堆栈)或者是否有任何 gdb 命令来找出线程特定的堆栈。
谢谢, 卡皮尔
【问题讨论】:
【参考方案1】:有没有办法让我们可以独占查看属于线程的栈
不存在这样的事情:所有线程共享整个地址空间,因此堆栈不会“独占”任何给定线程。事实上,您可以获取一个局部变量的地址,然后将该地址传递给不同的线程,然后该线程可以对其进行读取或写入值。
我相信您要问的是“如何判断 /proc/<pid>/maps
中的哪个内存区域是线程 X 当前用作其堆栈的?”。如果是这个问题,您可以print $sp
找出您感兴趣的线程的当前堆栈指针,然后在/proc/<pid>/maps
中找到与$sp
重叠的区域。
【讨论】:
事实上,看起来只有“主”线程(线程ID等于进程ID)的堆栈指针指向maps
中包含[stack]
的行文件,而其他线程的堆栈指针指向未命名的映射。【参考方案2】:
您可以使用info threads
列出所有线程
并使用thread <id>
切换到特定线程
您可以键入thread apply all info registers
来打印所有线程的当前寄存器。
或者例如 thread apply all bt
打印所有线程的回溯。
【讨论】:
【参考方案3】:@Employedrussian
There is no such thing: all the threads share the entire address space, so the stack
doesn't "belong exclusively" to any given thread. In fact, you can take an address of a
local variable, and pass that address to a different thread, which can then read or write
values to it.
What I believe you are asking is "how to tell which memory region in /proc/<pid>/maps is
thread X currently using as its stack?". If that's the question, you can print $sp to
find out current stack pointer for the thread you are interested in, and then find a
region in /proc/<pid>/maps that overlaps $sp.
是的,它们共享整个地址空间,线程也有自己的堆栈,但这仍然不能解释线程的堆栈与另一个线程或进程线程的堆栈有何不同。我的意思是,如果这是我们可以想象的方式:
+--------+ stack vma start
| +--+ |
| +--+ <------- stack of process
| +--+ |
| +--+ |
| : : |
| |
| |
| +--+ |
| +--+ <------- stack of thread1
| +--+ |
| +--+ |
| : : |
| |
| |
| +--+ |
| +--+ |
| +--+ <------ stack of thread2
| +--+ |
| : : |
: :
: :
+--------+ stack vma end
(可能我在这方面完全错了,但这只是试图澄清事情)
关于(局部变量)地址的传递,当您将其作为地址传递时,您可以读取或写入该内存位置,这是指针的固有属性。
【讨论】:
【参考方案4】:为了完整起见,我在这里提出我能理解的内容。
上面贴的图是错误的,应该这样修改:
Process address Space:
+----------------------------------------------------+
| |
: :
: :
| |
| +--------+ thread2 stack vma start |
| | +--+ | |
| | +--+ | |
| | +--+ | |
| | +--+ | | stack grows downwards |
| | : : | | |
| : : V |
| : : |
| +--------+ thread2 stack vma ends |
| |
| |
| +--------+ thread1 stack vma start |
| | +--+ | |
| | +--+ | |
| | +--+ | |
| | +--+ | | stack grows downwards |
| | : : | | |
| : : V |
| : : |
| +--------+ thread1 stack vma ends |
| |
| |
| +--------+ Process stack vma start |
| | +--+ | |
| | +--+ | |
| | +--+ | |
| | +--+ | | stack grows downwards |
| | : : | | |
| : : V |
: : : :
: +--------+ Process stack vma ends :
: :
+----------------------------------------------------+
thereads 从 mmap'd 内存中获取各自的堆栈。我说的是 glibc 中的 POSIX 实现。为了更好的参考参考函数 allocate_stack () 在 glibc 中的 nptl。
【讨论】:
以上是关于属于线程的堆栈与进程的堆栈有何不同的主要内容,如果未能解决你的问题,请参考以下文章