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的原因與解決方案