【发布时间】:2020-10-23 01:29:43
【问题描述】:
干草
我有一个关于内存中线程位置的问题,
线程堆栈位于哪里?有没有办法显示它(使用 gdb、readelf 或类似的东西)
【问题讨论】:
标签: c multithreading memory thread-safety pthreads
干草
我有一个关于内存中线程位置的问题,
线程堆栈位于哪里?有没有办法显示它(使用 gdb、readelf 或类似的东西)
【问题讨论】:
标签: c multithreading memory thread-safety pthreads
有没有办法显示它...使用 gdb...?
当然,GDB 可以显示任何线程的堆栈。我不记得命令,但它们就在手册中。 ISTR,有一个命令可以列出所有线程,还有一个命令用来告诉它你想查看哪个线程。其他一切都像单线程程序一样工作。
我认为还有一种方法可以告诉 GDB 迭代线程(即,对程序中的每个线程执行一次命令,例如转储堆栈)。
线程栈在哪里?
嗯,它位于内存中。
说真的。你为什么想知道?在我听说过的大多数编程环境中,一个线程的整个堆栈都是一次性分配的,而且它不能增长。如果默认大小不够大,程序通常可以通过某种方式说明它需要多大的新线程堆栈。
在 Linux 中,程序通常会通过调用'mmap(...)` 并带有允许操作系统选择虚拟地址的参数来为新线程的堆栈获取空间。但是,没有理由必须那样工作。如果有意义的话,程序可以从堆中分配堆栈。
在其他操作系统中,可能有一些类似于 mmap 的机制让操作系统选择地址。
如果你想要一个准确的答案,它在堆和堆栈之间的内存中
如果您回到 30 年或更长时间,类 Unix 操作系统中的进程将获得一个连续的虚拟内存块,通常从第一页开始(第零页将未分配,因为如果程序跟随一个 NULL 指针。)最低地址将包含程序的“文本”段(例如,它的代码和不可变字符串),然后是“数据”段(初始化的静态变量),然后是“bss”段(未初始化的静态变量) .)
从 BSS 顶部到给定 VM 区域顶部的所有内容都是“荒野”(即未触及)。程序的堆会从底部增长到荒野,而它唯一的调用堆栈将从顶部向下增长到荒野。如果堆和堆栈曾经相遇,那么您会收到“堆栈溢出”或malloc() 错误。
现在事情变得更加复杂了,一个程序可以有几十个甚至几百个调用堆栈。今天的 Linux 程序可以使用'mmap(...)` 来代替那种“荒野”来创建额外的 VM 区域——或者用于新线程的堆栈,或者添加到堆中,或者将文件映射到内存中以进行随机访问。
【讨论】: