Linux kernel 如何计算Linux下所有线程堆栈的总RSS?

Linux kernel 如何计算Linux下所有线程堆栈的总RSS?,linux-kernel,pthreads,Linux Kernel,Pthreads,我有一个Linux下的多线程应用程序,它消耗了大量内存,我正在尝试对它的RSS进行分类。我发现估算程序中所有线程堆栈的总RSS特别具有挑战性。我有以下想法: 概念1 < /强>:查看 /PRO//SMAP并考虑堆栈的映射;有关于每个映射的驻留大小的信息,但只有主线程映射被注释为[stack];其余部分与常规的8MIB映射(默认堆栈大小)无法区分。另外,读取/proc//smap的成本相当高,因为它会在内部VMA数据结构中的内核上产生争用 想法2:查看/proc//status;有VmStk部分

我有一个Linux下的多线程应用程序,它消耗了大量内存,我正在尝试对它的RSS进行分类。我发现估算程序中所有线程堆栈的总RSS特别具有挑战性。我有以下想法:

<强>概念1 < /强>:查看<代码> /PRO//SMAP并考虑堆栈的映射;有关于每个映射的驻留大小的信息,但只有主线程映射被注释为[stack];其余部分与常规的8MIB映射(默认堆栈大小)无法区分。另外,读取

/proc//smap
的成本相当高,因为它会在内部VMA数据结构中的内核上产生争用

想法2:查看
/proc//status
;有
VmStk
部分应该描述堆栈驻留的大小,但它总是显示主线程的堆栈大小。原因看起来很清楚:因为主线程是内核自己分配堆栈的唯一线程,而其余线程从pthreads代码获取堆栈,pthreads代码将堆栈作为常规内存映射进行分配

Idea 3:使用pthreads中的一些东西从用户空间遍历线程,检索每个线程的堆栈映射地址和堆栈大小,然后使用
mincore(2)
找出驻留的页面数量。作为一种可能的优化,我们可以跳过为睡眠线程调用mincore,为它们使用缓存值。不幸的是,我没有找到任何合适的方法来迭代
pthread\u t
结构。请注意,部分线程来自我无法控制的库,因此在启动时通过注册线程来维护任何类型的线程注册表都是不可能的

Idea 4:使用
ptrace(2)
检索线程寄存器,从中检索堆栈指针,然后继续执行Idea 1。这种方式看起来太难了

有谁能给我提供一个或多或少的方法来做到这一点?不可携带是可以的


经过额外的研究,我又得到了两个想法:

Idea 5:来自
/proc//maps
上的
man 5程序

              There are additional helpful pseudo-paths:

                   [stack]
                          The initial process's (also known as the main thread's) stack.

                   [stack:<tid>] (since Linux 3.4)
                          A thread's stack (where the <tid> is a thread ID).  It corresponds to the /proc/[pid]/task/[tid]/ path.
还有其他有用的伪路径:
[堆栈]
初始进程(也称为主线程)堆栈。
[堆栈:](自Linux 3.4起)
线程的堆栈(其中是线程ID)。它对应于/proc/[pid]/task/[tid]/路径。
这看起来很有趣,但似乎这一逻辑已经被还原,因为它的实现不成功:。手册页似乎过时了(至少在我的Ubuntu Disco 19.04上)


想法6:这一个可能确实有效。存在一个
/proc//syscall
文件,该文件可能会公开被阻止线程的线程堆栈寄存器。考虑到我的大多数线程都在I/O上睡眠,这允许我跟踪它们的rsp值,我可以将其投射到
/proc//maps
上,以找到线程与其堆栈映射之间的对应关系。在那之后,我可以实现想法3

,因为主线程是内核自己分配堆栈的唯一线程,而其余线程从pthreads获取堆栈
,所以从另一个方面来处理您的问题-获取pthres来告诉您线程的堆栈
pthread\u attr\u getstacksize
@KamilCuk这正是我在“idea 3”中尝试的,但我在pthread中没有找到任何合适的API来遍历所有线程。你知道怎么做吗?帕夫,我想你可以用
LD\u PRELOAD
屏蔽
pthread\u start
,并在一些数组中累积线程ID。好主意;相当技术性,但应该可以。我会把它作为备用计划,谢谢!