在Linux內(nèi)核開發(fā)中,Kmemleak是一種用于檢測(cè)內(nèi)核中內(nèi)存泄漏的工具。
內(nèi)存泄漏指的是程序中已經(jīng)不再使用的內(nèi)存沒有被妥善地釋放,導(dǎo)致內(nèi)存的浪費(fèi)。內(nèi)核中的內(nèi)存泄漏同樣會(huì)導(dǎo)致系統(tǒng)性能下降、系統(tǒng)崩潰等問題。
Kmemleak能夠檢測(cè)內(nèi)核中的內(nèi)存泄漏,通過檢測(cè)內(nèi)核中未被釋放但又無法找到其使用位置的內(nèi)存,進(jìn)一步定位、修復(fù)內(nèi)存泄漏的問題。
在用戶空間,我們常用
Valgrind來檢測(cè);在內(nèi)核空間,我們常用
Kmemleak來檢測(cè)。
?
內(nèi)核打開相應(yīng)配置:
CONFIG_DEBUG_KMEMLEAK:Kmemleak被加入到內(nèi)核CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設(shè)置為16000:該參數(shù)為記錄內(nèi)存泄露信息的內(nèi)存池,越大記錄信息越多。CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF :Kmemleak默認(rèn)開關(guān)狀態(tài)依賴的配置:
CONFIG_DEBUG_KERNEL:打開內(nèi)核調(diào)試功能CONFIG_DEBUG_FS:需要借助到debugfsCONFIG_STACKTRACE:記錄進(jìn)程的堆棧信息?
我們要想使用Kmemleak,需要掛在debugfs,來查看泄露的情況。
mount?-t?debugfs?nodev?/sys/kernel/debug/???#?掛在debugfs
echo?scan=10?>?/sys/kernel/debug/kmemleak???#?10S掃描一次
默認(rèn)內(nèi)存泄露檢測(cè)時(shí)間為
10min,上面設(shè)置為10s一次
cat?/sys/kernel/debug/kmemleak??????#?查看內(nèi)存泄露情況
echo?scan?>?/sys/kernel/debug/kmemleak??#觸發(fā)一次掃描
echo?clear?>?/sys/kernel/debug/kmemleak?????#清除當(dāng)前?kmemleak?記錄的泄露信息
echo?off?>?/sys/kernel/debug/kmemleak???????#關(guān)閉kmemleak(不可逆轉(zhuǎn)的)
echo?stack=off?>?/sys/kernel/debug/kmemleak?#關(guān)閉任務(wù)棧掃描
echo?stack=on?>?/sys/kernel/debug/kmemleak??#使能任務(wù)棧掃描
echo?scan=on?>?/sys/kernel/debug/kmemleak???#啟動(dòng)自動(dòng)內(nèi)存掃描線程
echo?scan=off?>?/sys/kernel/debug/kmemleak??#停止自動(dòng)內(nèi)存掃描線程
echo?scan=?>?/sys/kernel/debug/kmemleak#設(shè)置自動(dòng)掃描線程掃描間隔,默認(rèn)是600,設(shè)置0則是停止掃描
echo?dump=?>?/sys/kernel/debug/kmemleak?#dump某個(gè)地址的內(nèi)存塊信息,比如上面的echo?dump=0xffffffc008efd200?>?/sys/kernel/debug/kmemleak即可查看詳細(xì)信息
?
Kmemleak的默認(rèn)開關(guān)狀態(tài)可以通過CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF 配置來控制,當(dāng)然也可以通過向Linux內(nèi)核啟動(dòng)參數(shù)中加入kmemleak=off來控制。
?
Kmemleak提供了一種跟蹤垃圾回收器tracing garbage collector的原理,來檢測(cè)內(nèi)核中存在的內(nèi)存泄露,其不同之處在于:孤立的對(duì)象并沒有被釋放掉,而是通過/sys/kernel/debug/kmemleak僅僅被報(bào)告。
這種方法同樣應(yīng)用于
Valgrind中,不過該工具主要用于檢測(cè)用戶空間不同應(yīng)用的內(nèi)存泄露情況。在用戶空間,我們常用
Valgrind來檢測(cè)應(yīng)用進(jìn)程;在內(nèi)核空間,我們常用
Kmemleak來檢測(cè)內(nèi)核代碼。
通過kmalloc()、vmalloc()、kmem_cache_alloc()等函數(shù)分配內(nèi)存時(shí),會(huì)跟蹤指針,堆棧等信息,將其存儲(chǔ)在一個(gè)紅黑樹中。
同時(shí)跟蹤相應(yīng)的釋放函數(shù)調(diào)用,并從kmemleak數(shù)據(jù)結(jié)構(gòu)中刪除指針。
簡(jiǎn)單理解:相當(dāng)于追蹤內(nèi)存分配相關(guān)接口,記錄分配內(nèi)存的首地址,堆棧大小等信息,在內(nèi)存釋放階段將其刪除。
我們通過查看相關(guān)內(nèi)核文檔可知,內(nèi)存泄露檢測(cè)的掃描算法步驟如下:
?
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?-?更新對(duì)象分配堆棧跟蹤
kmemleak_not_leak?-?將對(duì)象標(biāo)記為非泄漏
kmemleak_ignore?-?不掃描或報(bào)告對(duì)象泄漏
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,但檢查遞歸性
?
漏報(bào):真正內(nèi)存泄露了,但是未報(bào)告,因?yàn)樵趦?nèi)存掃描期間找到的值指向此類對(duì)象。為了減少誤報(bào)的數(shù)量,kmemleak提供了kmemleak_ignore,kmemleak_scan_area,kmemleak_no_scan和kmemleak_erase功能
誤報(bào):實(shí)際沒有泄露,但是卻錯(cuò)誤的報(bào)告了內(nèi)存泄露。kmemleak提供了kmemleak_not_leak功能。
?
內(nèi)核也提供了一個(gè)示例:kmemleak-test模塊,該模塊用以判斷是否打開了Kmemleak功能。通過配置CONFIG_DEBUG_KMEMLEAK_TEST選項(xiàng)可以選擇。
#?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
...
?
?
本文來源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識(shí),版權(quán)歸原作者所有。如涉及作品版權(quán)問題,請(qǐng)聯(lián)系我進(jìn)行刪除。
由于微信公眾號(hào)近期改變了推送規(guī)則,為了防止找不到,可以星標(biāo)置頂,這樣每次推送的文章才會(huì)出現(xiàn)在您的訂閱列表里。
猜你喜歡:
談?wù)勄度胧杰浖募嫒菪裕?/strong>