属于线程的堆栈与进程的堆栈有何不同

Posted

技术标签:

【中文标题】属于线程的堆栈与进程的堆栈有何不同【英文标题】:How is a stack belonging to a thread different from a stack of a process 【发布时间】:2012-03-30 17:24:53 【问题描述】:

谁能告诉我这两种类型的堆栈有什么区别。

如果我看到 /proc/<pid>/mapproc/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。

【讨论】:

以上是关于属于线程的堆栈与进程的堆栈有何不同的主要内容,如果未能解决你的问题,请参考以下文章

一个进程最多包含多少个线程

在linux平台上用c/c++打印进程的所有线程堆栈跟踪

多线程基础知识

Java 进程与多线程

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

什么是进程?和线程区别?