slab_unreclaimable是指在Linux内存管理中由slab分配器分配的且被标记为不可回收(unreclaimable)的内存。当不可回收内存占用总内存的比例过高时,将会影响可用内存与系统性能。本文介绍如何排查Alibaba Cloud Linux系统slab_unreclaimable内存占用高的原因。
问题现象
在Linux实例内运行cat /proc/meminfo | grep "SUnreclaim"
命令查看SUnreclaim参数指标时,发现内存较大(例如SUnreclaim: 6069340 kB
),当该内存超过系统总内存大小的10%时,表示slab_unreclaimable内存占用过高,系统可能会存在slab内存泄露。
可能原因
在Linux内存管理中,slab内存是内核用于高效分配小块内存的一种缓存机制。内核组件或驱动程序通过调用内存分配接口(kmalloc等)向slab分配器申请内存,但是内核组件或驱动程序又没有正确释放内存,这将导致不可用内存越来越多,可用内存越来越少。
排查步骤
远程连接待排查问题的Linux实例。
具体操作,请参见连接方式概述。
运行以下命令,排查使用
objects
或内存较多,且内存不可回收的slab内存对应的名称。查看使用
objects
或内存最多的slab内存信息。slabtop -s -a
命令行返回结果中,您可以查看并记录
OBJ/SLAB
列数值较高的slab内存对应的名称(NAME
列)。确认slab内存是否为不可回收。
命令中的
<slab NAME>
变量需要手动修改为上一步中获取到的OBJ/SLAB
列数值较高的slab内存对应的名称。cat /sys/kernel/slab/<slab NAME>/reclaim_account
例如,查看名称为
kmalloc-192
的slab内存是否为不可回收。cat /sys/kernel/slab/kmalloc-192/reclaim_account
查询结果为0时,表示slab内存不可回收;查询结果为1时,表示slab内存可回收。
排查slab_unreclaimable内存占用高的原因。
您可以使用crash工具进行静态分析,也可以使用perf工具进行动态分析,排查造成slab内存泄露的原因。本文提供的示例场景中,存在slab泄露的内存名称为
kmalloc-192
。crash工具静态分析
运行以下命令,安装crash工具。
sudo yum install crash -y
运行以下命令,安装内核调试工具kernel-debuginfo。
Alibaba Cloud Linux 3
sudo yum install -y kernel-debuginfo-<内核版本> --enablerepo=alinux3-plus-debug
说明内核版本
需替换为系统实际的内核版本,通过uname -r
命令查询。Alibaba Cloud Linux 2
sudo yum install kernel-debuginfo -y
运行以下命令,启动crash工具。
sudo crash
在crash工具内,运行以下命令,查看
kmalloc-192
内存统计信息。kmem -S kmalloc-192
内存统计信息较多时,您可以设置只显示最后几行(例如10行)信息。
kmem -S kmalloc-192 | tail -n 10
命令行的返回结果示例如下:
SLAB MEMORY NODE TOTAL ALLOCATED FREE ffffea004c94e780 ffff88132539e000 0 42 29 13 ffffea004cbef900 ffff88132fbe4000 0 42 40 2 ffffea000a0e6280 ffff88028398a000 0 42 40 2 ffffea004bfa8000 ffff8812fea00000 0 42 41 1 ffffea006842b380 ffff881a10ace000 0 42 41 1 ffffea0009e7dc80 ffff880279f72000 0 42 34 8 ffffea004e67ae80 ffff881399eba000 0 42 40 2 ffffea00b18d6f80 ffff882c635be000 0 42 42 0
以
ffff88028398a000
统计信息为例,空闲内存较少(FREE
列),已分配的内存较多(ALLOCATED
列)。在crash工具内,运行以下命令,查看
ffff88028398a000
内存信息。rd ffff88028398a000 512 -S
命令行的返回信息较长,您可以根据命令行提示打印多个页面数据进行分析。例如:
返回信息中多次出现
put_cred_rcu
函数时,您可以自行查看Linux内核源码,搜索put_cred_rcu
函数。void __put_cred(struct cred *cred) { call_rcu(&cred->rcu, put_cred_rcu); }
查看到
put_cred_rcu
函数用于异步释放cred,且put_cred_rcu
出现在cred的末尾,表示是内核中cred结构体出现了slab内存泄露。
perf工具动态分析
运行以下命令,安装perf工具。
sudo yum install perf -y
运行以下命令,使用perf工具动态获取
kmalloc-192
中没有释放的内存,动态获取数据的时间间隔为200秒。sudo perf record -a -e kmem:kmalloc --filter 'bytes_alloc == 192' -e kmem:kfree --filter ' ptr != 0' sleep 200
在当前目录下,将动态获取的数据打印至临时文件中。
本示例中,临时文件名称为testperf.txt。
sudo perf script > testperf.txt
运行以下命令,查看testperf.txt文件内容。
cat testperf.txt
您需要手动排查没有空闲内存(
free
)的内存信息,然后在Linux内核源代码中手动查询产生slab内存泄露的函数。
通过crash和perf等工具确定了内存泄露的函数调用路径或者影响的内核数据结构后,建议在内核开发者或专业运维人员指导下确定内存泄露的具体源头,然后解决内存泄露问题。
以下是可能用到的一些解决方案,供您参考:
升级内核或补丁
调整内核参数
重启影响的服务或模块
优化应用程序或驱动
重启系统
相关文档
slab内存泄露会导致实例上运行的业务可用内存变少、内存碎片化,还会引起系统OOM Killer以及系统性能抖动等问题。
内存碎片化问题:Linux内存碎片化的应对措施
polkit内存泄露问题:如何解决Alibaba Cloud Linux 2中polkit内存泄露问题?
系统OOM Killer问题:出现OOM Killer的原因与解决方案