slub debug

内核存在内存泄漏时,通过kmemleak无法有效分析或怀疑是slab存在内存泄露,则可使用slabinfo信息进行debug。

配置slub debug

slub debug 功能需要在内核开启相关配置项才可以使用,主要配置项如下:

CONFIG_SLUB_DEBUG
CONFIG_SLUB_DEBUG_ON

其他依赖配置:

CONFIG_SYSFS

slabinfo信息

在完成配置之后,将会看到设备端有/proc/slabinfo节点,通过该节点,我们可以看到不同接口申请内存的信息:

root@Linux:/# cat /proc/slabinfo
slabinfo - version: 2.1
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
fuse_request           0      0    744   22    4 : tunables    0    0    0 : slabdata      0      0      0
fuse_inode             0      0   1152   14    4 : tunables    0    0    0 : slabdata      0      0      0
ubi_wl_entry_slab    490    506    368   22    2 : tunables    0    0    0 : slabdata     23     23      0
ubifs_inode_slab       0      0   1032   15    4 : tunables    0    0    0 : slabdata      0      0      0
bridge_fdb_cache       0      0    512   16    2 : tunables    0    0    0 : slabdata      0      0      0
ip6-frags              0      0    536   15    2 : tunables    0    0    0 : slabdata      0      0      0
fib6_nodes             0      0    512   16    2 : tunables    0    0    0 : slabdata      0      0      0
ip6_dst_cache          0      0    832   19    4 : tunables    0    0    0 : slabdata      0      0      0
ip6_mrt_cache          0      0    576   14    2 : tunables    0    0    0 : slabdata      0      0      0
RAWv6                  6     22   1472   22    8 : tunables    0    0    0 : slabdata      1      1      0
UDPLITEv6              0      0   1472   22    8 : tunables    0    0    0 : slabdata      0      0      0
UDPv6                  0      0   1472   22    8 : tunables    0    0    0 : slabdata      0      0      0
tw_sock_TCPv6          0      0    560   14    2 : tunables    0    0    0 : slabdata      0      0      0
request_sock_TCPv6      0      0    624   13    2 : tunables    0    0    0 : slabdata      0      0      0
TCPv6                  0      0   2432   13    8 : tunables    0    0    0 : slabdata      0      0      0
nf_conntrack_expect      0      0    560   14    2 : tunables    0    0    0 : slabdata      0      0      0
nf_conntrack           0      0    640   12    2 : tunables    0    0    0 : slabdata      0      0      0
aipu_job_cache         1     15    536   15    2 : tunables    0    0    0 : slabdata      1      1      0
sd_ext_cdb             2     22    368   22    2 : tunables    0    0    0 : slabdata      1      1      0
sgpool-128             2      7   4544    7    8 : tunables    0    0    0 : slabdata      1      1      0
sgpool-64              2     13   2496   13    8 : tunables    0    0    0 : slabdata      1      1      0
sgpool-32              2     22   1472   22    8 : tunables    0    0    0 : slabdata      1      1      0
sgpool-16              2     17    960   17    4 : tunables    0    0    0 : slabdata      1      1      0
sgpool-8               2     23    704   23    4 : tunables    0    0    0 : slabdata      1      1      0
cfq_io_cq              0      0    448   18    2 : tunables    0    0    0 : slabdata      0      0      0
cfq_queue              0      0    576   14    2 : tunables    0    0    0 : slabdata      0      0      0
fat_inode_cache        0      0   1032   15    4 : tunables    0    0    0 : slabdata      0      0      0
fat_cache              0      0    368   22    2 : tunables    0    0    0 : slabdata      0      0      0
squashfs_inode_cache    312    320   1024   16    4 : tunables    0    0    0 : slabdata     20     20      0
dnotify_mark           0      0    424   19    2 : tunables    0    0    0 : slabdata      0      0      0
dnotify_struct         0      0    368   22    2 : tunables    0    0    0 : slabdata      0      0      0
dio                    0      0   1152   14    4 : tunables    0    0    0 : slabdata      0      0      0
fasync_cache           0      0    384   21    2 : tunables    0    0    0 : slabdata      0      0      0
posix_timers_cache      0      0    560   14    2 : tunables    0    0    0 : slabdata      0      0      0
UNIX                  13     20   1600   20    8 : tunables    0    0    0 : slabdata      1      1      0
ip4-frags              0      0    552   14    2 : tunables    0    0    0 : slabdata      0      0      0
ip_mrt_cache           0      0    576   14    2 : tunables    0    0    0 : slabdata      0      0      0
UDP-Lite               0      0   1344   12    4 : tunables    0    0    0 : slabdata      0      0      0
tcp_bind_bucket        1     18    448   18    2 : tunables    0    0    0 : slabdata      1      1      0
inet_peer_cache        0      0    576   14    2 : tunables    0    0    0 : slabdata      0      0      0
ip_fib_trie            0      0    384   21    2 : tunables    0    0    0 : slabdata      0      0      0
ip_fib_alias           0      0    392   20    2 : tunables    0    0    0 : slabdata      0      0      0
ip_dst_cache           0      0    640   12    2 : tunables    0    0    0 : slabdata      0      0      0
RAW                    4     12   1280   12    4 : tunables    0    0    0 : slabdata      1      1      0
UDP                    1     24   1344   12    4 : tunables    0    0    0 : slabdata      2      2      0
tw_sock_TCP            0      0    560   14    2 : tunables    0    0    0 : slabdata      0      0      0
request_sock_TCP       0      0    624   13    2 : tunables    0    0    0 : slabdata      0      0      0
TCP                    1     14   2240   14    8 : tunables    0    0    0 : slabdata      1      1      0
eventpoll_pwq         11     20    408   20    2 : tunables    0    0    0 : slabdata      1      1      0
eventpoll_epi         11     28    576   14    2 : tunables    0    0    0 : slabdata      2      2      0
inotify_inode_mark      0      0    424   19    2 : tunables    0    0    0 : slabdata      0      0      0
scsi_data_buffer       0      0    360   22    2 : tunables    0    0    0 : slabdata      0      0      0
request_queue          1     14   2240   14    8 : tunables    0    0    0 : slabdata      1      1      0
blkdev_requests        0      0    696   23    4 : tunables    0    0    0 : slabdata      0      0      0
blkdev_ioc             5     18    440   18    2 : tunables    0    0    0 : slabdata      1      1      0
bio-0                  4     12    640   12    2 : tunables    0    0    0 : slabdata      1      1      0
biovec-max             4      7   4544    7    8 : tunables    0    0    0 : slabdata      1      1      0
biovec-128             0     13   2496   13    8 : tunables    0    0    0 : slabdata      1      1      0
biovec-64              0     22   1472   22    8 : tunables    0    0    0 : slabdata      1      1      0
biovec-16              0     23    704   23    4 : tunables    0    0    0 : slabdata      1      1      0
uid_cache              0      0    512   16    2 : tunables    0    0    0 : slabdata      0      0      0
dmaengine-unmap-2      1     18    448   18    2 : tunables    0    0    0 : slabdata      1      1      0
sock_inode_cache      38     48   1024   16    4 : tunables    0    0    0 : slabdata      3      3      0
skbuff_fclone_cache      0      0    832   19    4 : tunables    0    0    0 : slabdata      0      0      0
skbuff_head_cache      1     24    640   12    2 : tunables    0    0    0 : slabdata      2      2      0
configfs_dir_cache     30     38    424   19    2 : tunables    0    0    0 : slabdata      2      2      0
file_lock_cache        0     15    544   15    2 : tunables    0    0    0 : slabdata      1      1      0
file_lock_ctx          4     20    392   20    2 : tunables    0    0    0 : slabdata      1      1      0
shmem_inode_cache    243    256    984   16    4 : tunables    0    0    0 : slabdata     16     16      0
proc_inode_cache     121    128    968   16    4 : tunables    0    0    0 : slabdata      8      8      0
sigqueue               0     16    496   16    2 : tunables    0    0    0 : slabdata      1      1      0
bdev_cache             2     13   1216   13    4 : tunables    0    0    0 : slabdata      1      1      0
kernfs_node_cache  16881  16881    456   17    2 : tunables    0    0    0 : slabdata    993    993      0
mnt_cache             24     38    832   19    4 : tunables    0    0    0 : slabdata      2      2      0
filp                 150    240    640   12    2 : tunables    0    0    0 : slabdata     20     20      0
inode_cache         2814   2826    896   18    4 : tunables    0    0    0 : slabdata    157    157      0
dentry              3652   3660    528   15    2 : tunables    0    0    0 : slabdata    244    244      0
names_cache            0     35   4544    7    8 : tunables    0    0    0 : slabdata      5      5      0
buffer_head         5292   5292    440   18    2 : tunables    0    0    0 : slabdata    294    294      0
nsproxy                1     20    392   20    2 : tunables    0    0    0 : slabdata      1      1      0
vm_area_struct       386    520    792   20    4 : tunables    0    0    0 : slabdata     26     26      0
mm_struct             10     26   1216   13    4 : tunables    0    0    0 : slabdata      2      2      0
fs_cache              11     36    448   18    2 : tunables    0    0    0 : slabdata      2      2      0
files_cache           11     26   1216   13    4 : tunables    0    0    0 : slabdata      2      2      0
signal_cache          76    115   1408   23    8 : tunables    0    0    0 : slabdata      5      5      0
sighand_cache         76     91   2496   13    8 : tunables    0    0    0 : slabdata      7      7      0
task_struct           81     90   3456    9    8 : tunables    0    0    0 : slabdata     10     10      0
cred_jar              88    112    512   16    2 : tunables    0    0    0 : slabdata      7      7      0
anon_vma_chain       209    320    400   20    2 : tunables    0    0    0 : slabdata     16     16      0
anon_vma             131    220    408   20    2 : tunables    0    0    0 : slabdata     11     11      0
pid                   80     96    512   16    2 : tunables    0    0    0 : slabdata      6      6      0
kmemleak_scan_area   4035   4048    368   22    2 : tunables    0    0    0 : slabdata    184    184      0
kmemleak_object    55398  55800    640   12    2 : tunables    0    0    0 : slabdata   4650   4650      0
radix_tree_node      216    221    912   17    4 : tunables    0    0    0 : slabdata     13     13      0
pool_workqueue         4     16   1024   16    4 : tunables    0    0    0 : slabdata      1      1      0
idr_layer_cache      191    195   2432   13    8 : tunables    0    0    0 : slabdata     15     15      0
task_group             4     18    896   18    4 : tunables    0    0    0 : slabdata      1      1      0
dma-kmalloc-8192       0      0   8704    3    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-4096       0      0   4608    7    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-2048       0      0   2560   12    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-1024       0      0   1536   21    8 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-512        0      0   1024   16    4 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-256        0      0    768   21    4 : tunables    0    0    0 : slabdata      0      0      0
dma-kmalloc-128        0      0    640   12    2 : tunables    0    0    0 : slabdata      0      0      0
kmalloc-8192          10     12   8704    3    8 : tunables    0    0    0 : slabdata      4      4      0
kmalloc-4096          39     42   4608    7    8 : tunables    0    0    0 : slabdata      6      6      0
kmalloc-2048         116    120   2560   12    8 : tunables    0    0    0 : slabdata     10     10      0
kmalloc-1024         468    483   1536   21    8 : tunables    0    0    0 : slabdata     23     23      0
kmalloc-512          550    560   1024   16    4 : tunables    0    0    0 : slabdata     35     35      0
kmalloc-256         1390   1428    768   21    4 : tunables    0    0    0 : slabdata     68     68      0
kmalloc-128        19391  19404    640   12    2 : tunables    0    0    0 : slabdata   1617   1617      0
kmem_cache_node      113    120    640   12    2 : tunables    0    0    0 : slabdata     10     10      0
kmem_cache           113    126    768   21    4 : tunables    0    0    0 : slabdata      6      6      0

上面的alsbinfo信息,我们可以知道不同api申请的内存数量。如果存在内存泄漏,我们将可以通过对比上面的信息,知道是哪个API被调用申请内存最后存在泄漏。

slabinfo 排查

假设我们通过前后两次的对比,发现kmalloc-128的num_objs较之前存在明显的增长,那么首先怀疑驱动是通过 kmalloc-128 申请内存后存在泄漏的情况。

这个时候可以通过 cat /sys/kernel/slab/kmalloc-128/alloc_calls命令了解到都有哪些驱动的API申请了 kmalloc-128。也是通过前后对比该节点的信息,从而指导明显存在差异的API,从而定位问题。

在执行 cat /sys/kernel/slab/kmalloc-128/alloc_calls

命令的时候,往往因为申请内存的API过多从而导致无法完整打印,这个时候我往往会自己增加一个补丁:

diff --git a/mm/slub.c b/mm/slub.c
index bdbb20631ca8..95ee1e7ba3bc 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4552,6 +4552,9 @@ static int list_locations(struct kmem_cache *s, char *buf,
        for (i = 0; i < t.count; i++) {
                struct location *l = &t.loc[i];

+               if (l->count < 1000)
+                       continue;
+
                if (len > PAGE_SIZE - KSYM_SYMBOL_LEN - 100) {
                        print_buf = true;
                        pr_err("%s\n", buf);

增加上面的补丁,通过某一API调用申请的slab对象小于1000则不打印出来,从而可以明显对比前后差异了(泄漏是反复调用某一API导致的可明显看到差异,而阈值可以自行调整)。

得到某一API调用后,再查找驱动是哪一个驱动调用到该API即可,逐步排查。

抓取 slab 对象的 trace 信息

在抓出 slab 对象的 alloc_calls 和 free_calls 分析,不一定可以有效的分析出问题,这时就需要抓取泄露场景的 slab 对象的 trace 信息进行分析了,使用如下命令抓取 trace 信息:

echo 0 > /proc/sys/kernel/printk //先设置打印等级为0,否则串口控制台log输出过多
echo 1 >/sys/kernel/slab/kmalloc-128/trace;cat /proc/kmsg > /tmp/slab_trace.txt

分析抓取到的 slab_trace.txt 文件,观察 slab 对象的 alloc 和 free 是否正常。这个方式可能会存在kmsg log被覆盖的情况,log的buf不够大,可通过设置 CONFIG_LOG_BUF_SHIFT的值,设置log buf的大小:

	17 => 128 KB
	16 => 64 KB
	15 => 32 KB
	14 => 16 KB
	13 =>  8 KB
	12 =>  4 KB

通过 slab_trace.txt 可以得到申请slab对象的地方,然后再查找内核是哪一个驱动调用到该API即可,逐步排查。

猜你喜欢

转载自blog.csdn.net/weixin_41944449/article/details/123441912