寻找内核空间里的内存大户——扩展命令 !ndx.slab详解
实现原理
从Linux内核的全局变量slab_caches获取链表的头地址,进行遍历。
示例:
ffffffff9ce6d6f0 t slab_caches_to_rcu_destroy_workfn
ffffffff9e2eab40 d slab_caches_to_rcu_destroy_work
ffffffff9e2eab60 d slab_caches_to_rcu_destroy
ffffffff9e2eaba0 D slab_caches
得到kmem_cache结构体的信息。
(图片所示信息在NDB中输入dt lk!kmem_cache就能查看,缺少内核信息文件解决方法见下文)
此结构体是用来管理slab的结构体,每一个kmem_cache结构体对应描述的一段内存就是一个slab缓存池。slub分配器将从伙伴系统得到的连续内存平均分成若干大小相等的object(对象)进行管理。
其中的一些信息:
struct kmem_cache {
struct kmem_cache_cpu __percpu *cpu_slab;
/* Used for retriving partial slabs etc */
slab_flags_t flags;
unsigned long min_partial;
int size; /* The size of an object including meta data */
int object_size; /* The size of an object without meta data */
int offset; /* Free pointer offset. */
#ifdef CONFIG_SLUB_CPU_PARTIAL
int cpu_partial; /* Number of per cpu partial objects to keep around */
#endif
struct kmem_cache_order_objects oo;
/* Allocation and freeing of slabs */
struct kmem_cache_order_objects max;
struct kmem_cache_order_objects min;
gfp_t allocflags; /* gfp flags to use on each alloc */
int refcount; /* Refcount for slab cache destroy */
void (*ctor)(void *);
int inuse; /* Offset to metadata */
int align; /* Alignment */
int reserved; /* Reserved bytes at the end of slabs */
const char *name; /* Name (only for display!) */
unsigned int useroffset;/* Usercopy region offset */
unsigned int usersize; /* Usercopy region size */
struct list_head list; /* List of slab caches */
struct kmem_cache_node *node[MAX_NUMNODES];
};
- cpu_slab:一个per cpu变量。相当于一个本地内存缓存池,当分配内存的时候优先从本地cpu分配内存。
- flags:object分配掩码,例如经常使用的SLAB_HWCACHE_ALIGN标志位,代表创建的kmem_cache管理的object按照硬件cache 对齐。
- name:供显示使用的文件名字。
- size:分配的object size。
- object_size:实际的object size,就是创建kmem_cache时候传递进来的参数。和size的关系就是,size是各种地址对齐之后的大小。因此,size要大于等于object_size。
- oo:低16位代表一个slab中所有object的数量,高16位代表一个slab管理的page数量。
- list:所有的slab都会挂入链表,因此遍历此信息就可以得到所有slab信息。
- inuse:object_size对齐之后的大小。
- align:字节对齐大小。
得到所有的信息后输出汇总。
具体使用
- 直接输入
!ndx.slab
。
如果出现如上图所示的提示,那么缺少加载内核信息的文件。
文件示例如下:
输入.sympath 文件全路径
,然后再输入.reload
即可。
例如输入.sympath d:\wucheng
,然后输入.reload
加载此文件夹即可。
您可以输入lm
查看
说明加载成功了。
- 再次输入
!ndx.slab
会逐个输出slab分配器状态,并最后按照总数排序输出(从大到小排序)。需要大约一分半时间读取。
如下图所示
当逐个输出slab分配器结束后,进行名字分类汇总,从小到大排序。这样我们就能看到谁占用了较多的内存了。
其中 - total_obj=size X num_obj
- num_obj=objperslab X slab数目
比如:
图中的ext4_inode_cache,我们能看到它占用的空间很大,虽然size不是很大但是其object的数目很大,因而占用内存也很大。它占用的slab数量是1350/27=50,也就是说上图中显示的kmem_cache中有50个都用来存储ext4_inode_cache。
向上翻找也能找到很多,
比如
等等。
作者:YuQing 创建时间:2022-07-19 10:42
最后编辑:YuQing 更新时间:2024-10-10 17:15
最后编辑:YuQing 更新时间:2024-10-10 17:15