命令字:!ndx.slab

用法描述

输出Linux 内核 slab 分配器的详细统计信息,相当于cat /proc/slabinfo
命令行参数支持:
-o 表示按单个对象大小排序
-t 表示按所有对象的总大小排序
-n 表示按对象数量排序

开发过程

1.找到关键全局变量

在内核 mm\slab_common.c文件中
proc_create(“slabinfo”, SLABINFO_RIGHTS, NULL, &slabinfo_proc_ops);在proc文件系统中创建了文件slabinfo,并且注册了相关执行的回调函数,如read,write,open
.proc_open = slabinfo_open是打开文件时候调用的回调函数,实际操作由结构体slabinfo_op封装的四个回调函数(.start,.next,.stop,.show)完成

seq_list_start(&slab_caches, *pos);用于确定遍历链表的起点,传入的全局变量slab_caches即为链表的头结点。

seq_list_next(p, &slab_caches, pos);用于遍历链表,在具体的实现中我们可以知道,如果返回头结点即为结束。

在内核的链表节点结构体list_head的定义中有前驱指针和后继指针,也说明这是一个双向循环链表。

2.相关数据结构

list_entry(p, struct kmem_cache, list);通过链表节点指针反向获取包含该节点的结构体kmem_cache指针。

定义一个局部变量struct slabinfo sinfo 用于打印相关信息
调用get_slabinfo(s,&sinfo);从结构体 kmem_cache中获取数据。

在get_slabinfo这个函数中,又定义了一个局部变量struct kmem_cache_node *n
用于遍历kmem_cache中的某个字段数组时,获取数据,做进一步的处理。

所以说:struct slabinfo sinfo(最终打印的相关信息) 具体要通过kmem_cache中的某个字段数组来获取信息

继续深入发现是名为node的数组。

在Nanocode 使用dt命令查看kmenm_cache结构体的结构可以看到这个数组。

根据这里的打印,去到对应的结构中读取数据,处理后输出即可

3.读取变量和相关偏移,输出信息

DECLARE_API(slab)
{

    ULONG64 Address, FirstAddress;
    ULONG FieldOffset;
    const char* option, * filename;

    dprintf("Reading slabinfo of Linux kernel\n");

    if (args[0] == '?') {
        dprintf("-o Sort by single object size\n");
        dprintf("-t Sort by total size of all objects\n");
        dprintf("-n Sort by number of objects\n");
        dprintf("-? Display option information\n");
        return;
    }

    GetExpressionEx("lk!slab_caches", &FirstAddress, NULL);
    GetFieldValue(FirstAddress, "list_head", "next", Address);
    GetFieldOffset("kmem_cache", "list", &FieldOffset);
    dprintf("kmem_cache=%11x\n", FieldOffset);
    if (FieldOffset == 0)
    {
        dprintf("failed to get FieldOffset\n");
        return;
    }
    dprintf("slab_caches = %llx\n", FirstAddress);
    if (FirstAddress == 0) {
        dprintf("failed read FirstAddress\n");
        // failed
        return;
    }
    dprintf("kmem_cache_addr: %p\n", FirstAddress - FieldOffset);
    dprintf(" name                                                       total_obj       num_obj   objperslab    object_size   size  align useroffset usersize refcount      \n");
    ShowSlabWithSortBySize(FirstAddress, Address, FieldOffset);

}
/*slab扩展命令结束*/

4.实例测试

!ndx.slab

cat /proc/slabinfo

作者:郭建程  创建时间:2025-09-10 11:08
最后编辑:郭建程  更新时间:2025-09-11 16:05