Linux內(nèi)核內(nèi)存泄漏怎么搞?
1、Kmemleak介紹
在Linux內(nèi)核開發(fā)中,Kmemleak是一種用于檢測內(nèi)核中內(nèi)存泄漏的工具。
內(nèi)存泄漏指的是程序中已經(jīng)不再使用的內(nèi)存沒有被妥善地釋放,導致內(nèi)存的浪費。內(nèi)核中的內(nèi)存泄漏同樣會導致系統(tǒng)性能下降、系統(tǒng)崩潰等問題。
Kmemleak能夠檢測內(nèi)核中的內(nèi)存泄漏,通過檢測內(nèi)核中未被釋放但又無法找到其使用位置的內(nèi)存,進一步定位、修復內(nèi)存泄漏的問題。
在用戶空間,我們常用Valgrind來檢測;
在內(nèi)核空間,我們常用Kmemleak來檢測。
2、如何使用Kmemleak
2.1 內(nèi)核配置
內(nèi)核打開相應配置:
CONFIG_DEBUG_KMEMLEAK:Kmemleak被加入到內(nèi)核
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設置為16000:該參數(shù)為記錄內(nèi)存泄露信息的內(nèi)存池,越大記錄信息越多。
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF :Kmemleak默認開關(guān)狀態(tài)
依賴的配置:
CONFIG_DEBUG_KERNEL:打開內(nèi)核調(diào)試功能
CONFIG_DEBUG_FS:需要借助到debugfs
CONFIG_STACKTRACE:記錄進程的堆棧信息
2.2 用戶空間配置
我們要想使用Kmemleak,需要掛在debugfs,來查看泄露的情況。
進入文件系統(tǒng)后,進行掛載:
?
mount?-t?debugfs?nodev?/sys/kernel/debug/???#?掛在debugfs
?
設置掃描時間:
?
echo?scan=10?>?/sys/kernel/debug/kmemleak???#?10S掃描一次
?
默認內(nèi)存泄露檢測時間為10min,上面設置為10s一次
查看泄露情況:
?
cat?/sys/kernel/debug/kmemleak??????#?查看內(nèi)存泄露情況
?
其他指令:
?
echo?scan?>?/sys/kernel/debug/kmemleak??#觸發(fā)一次掃描 echo?clear?>?/sys/kernel/debug/kmemleak?????#清除當前?kmemleak?記錄的泄露信息 echo?off?>?/sys/kernel/debug/kmemleak???????#關(guān)閉kmemleak(不可逆轉(zhuǎn)的) echo?stack=off?>?/sys/kernel/debug/kmemleak?#關(guān)閉任務棧掃描 echo?stack=on?>?/sys/kernel/debug/kmemleak??#使能任務棧掃描 echo?scan=on?>?/sys/kernel/debug/kmemleak???#啟動自動內(nèi)存掃描線程 echo?scan=off?>?/sys/kernel/debug/kmemleak??#停止自動內(nèi)存掃描線程 echo?scan=?>?/sys/kernel/debug/kmemleak#設置自動掃描線程掃描間隔,默認是600,設置0則是停止掃描 echo?dump= ?>?/sys/kernel/debug/kmemleak?#dump某個地址的內(nèi)存塊信息,比如上面的echo?dump=0xffffffc008efd200?>?/sys/kernel/debug/kmemleak即可查看詳細信息
?
2.3 通過Linux啟動參數(shù)控制開關(guān)
Kmemleak的默認開關(guān)狀態(tài)可以通過CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF 配置來控制,當然也可以通過向Linux內(nèi)核啟動參數(shù)中加入kmemleak=off來控制。
3、Kmemleak原理
Kmemleak提供了一種跟蹤垃圾回收器tracing garbage collector的原理,來檢測內(nèi)核中存在的內(nèi)存泄露,其不同之處在于:孤立的對象并沒有被釋放掉,而是通過/sys/kernel/debug/kmemleak僅僅被報告。
這種方法同樣應用于Valgrind中,不過該工具主要用于檢測用戶空間不同應用的內(nèi)存泄露情況。
在用戶空間,我們常用Valgrind來檢測應用進程;
在內(nèi)核空間,我們常用Kmemleak來檢測內(nèi)核代碼。
通過kmalloc()、vmalloc()、kmem_cache_alloc()等函數(shù)分配內(nèi)存時,會跟蹤指針,堆棧等信息,將其存儲在一個紅黑樹中。
同時跟蹤相應的釋放函數(shù)調(diào)用,并從kmemleak數(shù)據(jù)結(jié)構(gòu)中刪除指針。
簡單理解:相當于追蹤內(nèi)存分配相關(guān)接口,記錄分配內(nèi)存的首地址,堆棧大小等信息,在內(nèi)存釋放階段將其刪除。
我們通過查看相關(guān)內(nèi)核文檔可知,內(nèi)存泄露檢測的掃描算法步驟如下:
將所有對象標記為白色(最后剩余的白色對象將被視為孤立對象)
從數(shù)據(jù)段和堆棧開始掃描內(nèi)存,根據(jù)紅黑樹中存儲的地址信息來檢查值,如果找到指向白色對象的指針,則添加到灰色列表
掃描灰色列表以查找地址匹配的對象,直到灰色列表完成
剩下的白色對象被視為孤立對象,并通過/sys/kernel/debug/kmemleak進行報告
4、Kmemleak API接口
?
kmemleak_init?-?初始化?kmemleak kmemleak_alloc?-?內(nèi)存塊分配通知 kmemleak_alloc_percpu?-?通知?percpu?內(nèi)存塊分配 kmemleak_vmalloc?-?通知?vmalloc()?內(nèi)存分配 kmemleak_free?-?通知內(nèi)存塊釋放 kmemleak_free_part?-?通知釋放部分內(nèi)存塊 kmemleak_free_percpu?-?通知?percpu?內(nèi)存塊釋放 kmemleak_update_trace?-?更新對象分配堆棧跟蹤 kmemleak_not_leak?-?將對象標記為非泄漏 kmemleak_ignore?-?不掃描或報告對象泄漏 kmemleak_scan_area?-?在內(nèi)存塊內(nèi)添加掃描區(qū)域 kmemleak_no_scan?-?不掃描內(nèi)存塊 kmemleak_erase?-?擦除指針變量中的舊值 kmemleak_alloc_recursive?-?作為kmemleak_alloc,但檢查遞歸性 kmemleak_free_recursive?-?作為kmemleak_free,但檢查遞歸性
?
5、Kmemleak特殊情況
漏報:真正內(nèi)存泄露了,但是未報告,因為在內(nèi)存掃描期間找到的值指向此類對象。為了減少誤報的數(shù)量,kmemleak提供了kmemleak_ignore,kmemleak_scan_area,kmemleak_no_scan和kmemleak_erase功能
誤報:實際沒有泄露,但是卻錯誤的報告了內(nèi)存泄露。kmemleak提供了kmemleak_not_leak功能。
6、Kmemleak驗證
內(nèi)核也提供了一個示例:kmemleak-test模塊,該模塊用以判斷是否打開了Kmemleak功能。通過配置CONFIG_DEBUG_KMEMLEAK_TEST選項可以選擇。
?
#?modprobe?kmemleak-test #?echo?scan?>?/sys/kernel/debug/kmemleak
#?cat?/sys/kernel/debug/kmemleak unreferenced?object?0xffff89862ca702e8?(size?32): ??comm?"modprobe",?pid?2088,?jiffies?4294680594?(age?375.486s) ??hex?dump?(first?32?bytes): ????6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b??kkkkkkkkkkkkkkkk ????6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?6b?a5??kkkkkkkkkkkkkkk. ??backtrace: ????[<00000000e0a73ec7>]?0xffffffffc01d2036 ????[<000000000c5d2a46>]?do_one_initcall+0x41/0x1df ????[<0000000046db7e0a>]?do_init_module+0x55/0x200 ????[<00000000542b9814>]?load_module+0x203c/0x2480 ????[<00000000c2850256>]?__do_sys_finit_module+0xba/0xe0 ????[<000000006564e7ef>]?do_syscall_64+0x43/0x110 ????[<000000007c873fa6>]?entry_SYSCALL_64_after_hwframe+0x44/0xa9 ...
?
電子發(fā)燒友App










































評論