如何在较新的 Linux 内核中查找堆栈内存段



我有一个小库,它写出一个"瘦核心",它只包含堆栈信息(以及有效核心所需的其他位(,但不包括任何堆。 这并不总是有用的,但核心比完整核心小得多,有时人们不想提供堆的内容。

该库通过读取/proc/<PID>/maps并定位[stack][stack:<tid>]段(此过程有很多线程(来工作。 例如,我会看到这样的输出:

...
7fe848000000-7fe848021000 rw-p 00000000 00:00 0 
7fe848021000-7fe84c000000 ---p 00000000 00:00 0 
7fe84c1ff000-7fe84c200000 ---p 00000000 00:00 0 
7fe84c200000-7fe84ca00000 rw-p 00000000 00:00 0    [stack:25672]
7fe84ca00000-7fe84cc00000 rw-p 00000000 00:00 0 
7fe84cdff000-7fe84ce00000 ---p 00000000 00:00 0 
7fe84ce00000-7fe84d600000 rw-p 00000000 00:00 0    [stack:25534]
7fe84d600000-7fe84d800000 rw-p 00000000 00:00 0 
7fe84d9ff000-7fe84da00000 ---p 00000000 00:00 0 
7fe84da00000-7fe84e200000 rw-p 00000000 00:00 0    [stack:25532]
7fe84e200000-7fe84e600000 rw-p 00000000 00:00 0 
7fe84e7fd000-7fe84e7fe000 ---p 00000000 00:00 0 
7fe84e7fe000-7fe84effe000 rw-p 00000000 00:00 0    [stack:25531]
7fe84effe000-7fe84efff000 ---p 00000000 00:00 0 
7fe84efff000-7fe84f7ff000 rw-p 00000000 00:00 0    [stack:25530]
7fe84f7ff000-7fe84f800000 ---p 00000000 00:00 0 
7fe84f800000-7fe850000000 rw-p 00000000 00:00 0    [stack:25529]
7fe850000000-7fe850021000 rw-p 00000000 00:00 0 
7fe850021000-7fe854000000 ---p 00000000 00:00 0 
7fe854000000-7fe854400000 rw-p 00000000 00:00 0 
7fe8545ff000-7fe854600000 ---p 00000000 00:00 0
...
7fff5ce1d000-7fff5ce3e000 rw-p 00000000 00:00 0    [stack]
...

等。 这在较旧的Linux内核(如3.5(Ubuntu 12.04(和3.13(Ubuntu 14.04((上运行良好。

但是,对于较新的内核(例如 Ubuntu 16.04 的 4.4(,/proc/<PID>/maps文件似乎不再包含每线程堆栈段的任何条目。 我只看到主堆栈[stack];所有看起来像是堆栈段的内存段都有一个空的路径名部分。

这意味着我的"薄内核"太薄了,只提供了主线程的堆栈。

我尝试在较新的内核中检查/proc/<PID>/smaps,但我找不到一种方法来确定哪些段与线程堆栈相关联,哪些段与线程堆栈无关,采用新的更有限的格式。

我也检查了 procfs(5( 手册页,它仍然列出了我应该看到的[stack:<tid>]格式,但我没有看到它......

任何人都知道这些信息去了哪里,我是否可以从其他一些可用信息中推断出来?

我还没有找到解决这个问题的真正方法。 为了后代,我将描述我在短期内所做的事情:我使用pthread_attr_getstacksize()获得了线程堆栈的大小,然后当我查看未命名的内存段以决定写入"薄核心"的内容时,我保留了具有该确切大小的段,而忽略了其余的。

这是一个非常狡猾的启发式方法,但这是我能想到的,而且它似乎与我有限的测试相去甚远。

我仍然希望有人能提供更可靠/更强大的替代方案。