快報:Linux內核內存泄漏怎么辦

2023-07-04 11:18:36 來源:嵌入式藝術

Linux內核內存泄漏怎么搞?

1、Kmemleak介紹

在Linux內核開發中,Kmemleak是一種用于檢測內核中內存泄漏的工具。


(資料圖片)

內存泄漏指的是程序中已經不再使用的內存沒有被妥善地釋放,導致內存的浪費。內核中的內存泄漏同樣會導致系統性能下降、系統崩潰等問題。

Kmemleak能夠檢測內核中的內存泄漏,通過檢測內核中未被釋放但又無法找到其使用位置的內存,進一步定位、修復內存泄漏的問題。

在用戶空間,我們常用Valgrind來檢測;

在內核空間,我們常用Kmemleak來檢測。

2、如何使用Kmemleak

2.1 內核配置

內核打開相應配置

CONFIG_DEBUG_KMEMLEAK:Kmemleak被加入到內核

CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設置為16000:該參數為記錄內存泄露信息的內存池,越大記錄信息越多。

CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF :Kmemleak默認開關狀態

依賴的配置

CONFIG_DEBUG_KERNEL:打開內核調試功能

CONFIG_DEBUG_FS:需要借助到debugfs

CONFIG_STACKTRACE:記錄進程的堆棧信息

2.2 用戶空間配置

我們要想使用Kmemleak,需要掛在debugfs,來查看泄露的情況。

進入文件系統后,進行掛載

mount-tdebugfsnodev/sys/kernel/debug/#掛在debugfs

設置掃描時間

echoscan=10>/sys/kernel/debug/kmemleak#10S掃描一次

默認內存泄露檢測時間為10min,上面設置為10s一次

查看泄露情況

cat/sys/kernel/debug/kmemleak#查看內存泄露情況

其他指令

echoscan>/sys/kernel/debug/kmemleak#觸發一次掃描echoclear>/sys/kernel/debug/kmemleak#清除當前kmemleak記錄的泄露信息echooff>/sys/kernel/debug/kmemleak#關閉kmemleak(不可逆轉的)echostack=off>/sys/kernel/debug/kmemleak#關閉任務棧掃描echostack=on>/sys/kernel/debug/kmemleak#使能任務棧掃描echoscan=on>/sys/kernel/debug/kmemleak#啟動自動內存掃描線程echoscan=off>/sys/kernel/debug/kmemleak#停止自動內存掃描線程echoscan=>/sys/kernel/debug/kmemleak#設置自動掃描線程掃描間隔,默認是600,設置0則是停止掃描echodump=>/sys/kernel/debug/kmemleak#dump某個地址的內存塊信息,比如上面的echodump=0xffffffc008efd200>/sys/kernel/debug/kmemleak即可查看詳細信息

2.3 通過Linux啟動參數控制開關

Kmemleak的默認開關狀態可以通過CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF 配置來控制,當然也可以通過向Linux內核啟動參數中加入kmemleak=off來控制。

3、Kmemleak原理

Kmemleak提供了一種跟蹤垃圾回收器tracing garbage collector的原理,來檢測內核中存在的內存泄露,其不同之處在于:孤立的對象并沒有被釋放掉,而是通過/sys/kernel/debug/kmemleak僅僅被報告。

這種方法同樣應用于Valgrind中,不過該工具主要用于檢測用戶空間不同應用的內存泄露情況。

在用戶空間,我們常用Valgrind來檢測應用進程;

在內核空間,我們常用Kmemleak來檢測內核代碼。

通過kmalloc()、vmalloc()、kmem_cache_alloc()等函數分配內存時,會跟蹤指針,堆棧等信息,將其存儲在一個紅黑樹中。

同時跟蹤相應的釋放函數調用,并從kmemleak數據結構中刪除指針。

簡單理解:相當于追蹤內存分配相關接口,記錄分配內存的首地址,堆棧大小等信息,在內存釋放階段將其刪除。

我們通過查看相關內核文檔可知,內存泄露檢測的掃描算法步驟如下:

將所有對象標記為白色(最后剩余的白色對象將被視為孤立對象)

從數據段和堆棧開始掃描內存,根據紅黑樹中存儲的地址信息來檢查值,如果找到指向白色對象的指針,則添加到灰色列表

掃描灰色列表以查找地址匹配的對象,直到灰色列表完成

剩下的白色對象被視為孤立對象,并通過/sys/kernel/debug/kmemleak進行報告

4、Kmemleak API接口

kmemleak_init-初始化kmemleakkmemleak_alloc-內存塊分配通知kmemleak_alloc_percpu-通知percpu內存塊分配kmemleak_vmalloc-通知vmalloc()內存分配kmemleak_free-通知內存塊釋放kmemleak_free_part-通知釋放部分內存塊kmemleak_free_percpu-通知percpu內存塊釋放kmemleak_update_trace-更新對象分配堆棧跟蹤kmemleak_not_leak-將對象標記為非泄漏kmemleak_ignore-不掃描或報告對象泄漏kmemleak_scan_area-在內存塊內添加掃描區域kmemleak_no_scan-不掃描內存塊kmemleak_erase-擦除指針變量中的舊值kmemleak_alloc_recursive-作為kmemleak_alloc,但檢查遞歸性kmemleak_free_recursive-作為kmemleak_free,但檢查遞歸性

5、Kmemleak特殊情況

漏報:真正內存泄露了,但是未報告,因為在內存掃描期間找到的值指向此類對象。為了減少誤報的數量,kmemleak提供了kmemleak_ignore,kmemleak_scan_area,kmemleak_no_scan和kmemleak_erase功能

誤報:實際沒有泄露,但是卻錯誤的報告了內存泄露。kmemleak提供了kmemleak_not_leak功能。

6、Kmemleak驗證

內核也提供了一個示例:kmemleak-test模塊,該模塊用以判斷是否打開了Kmemleak功能。通過配置CONFIG_DEBUG_KMEMLEAK_TEST選項可以選擇。

#modprobekmemleak-test#echoscan>/sys/kernel/debug/kmemleak
#cat/sys/kernel/debug/kmemleakunreferencedobject0xffff89862ca702e8(size32):comm"modprobe",pid2088,jiffies4294680594(age375.486s)hexdump(first32bytes):6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6bkkkkkkkkkkkkkkkk6b6b6b6b6b6b6b6b6b6b6b6b6b6b6ba5kkkkkkkkkkkkkkk.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...
審核編輯:湯梓紅

標簽:

上一篇:當前信息:聯想小新520智能投影儀拆解詳細報告
下一篇:最后一頁