最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

詳細講解Linux內(nèi)存泄漏檢測實現(xiàn)原理與實現(xiàn)

2022-11-21 15:27 作者:補給站Linux內(nèi)核  | 我要投稿

在使用沒有垃圾回收的語言時(如 C/C++),可能由于忘記釋放內(nèi)存而導(dǎo)致內(nèi)存被耗盡,這叫 內(nèi)存泄漏。由于內(nèi)核也需要自己管理內(nèi)存,所以也可能出現(xiàn)內(nèi)存泄漏的情況。為了能夠找出導(dǎo)致內(nèi)存泄漏的地方,Linux 內(nèi)核開發(fā)者開發(fā)出 kmemleak 功能。

下面我們來詳細介紹一下 kmemleak 這個功能的原理與實現(xiàn)。

kmemleak 原理

首先來分析一下,什么情況會導(dǎo)致 內(nèi)存泄漏。

1. 造成內(nèi)存泄漏的原因

內(nèi)存泄漏的根本原因是由于用戶沒有釋放不再使用的動態(tài)申請的內(nèi)存(在內(nèi)核中由 memblock_alloc、kmalloc、vmalloc、kmem_cache_alloc 等函數(shù)申請的內(nèi)存),那么哪些內(nèi)存是不再使用的呢?一般來說,沒有被指針引用(指向)的內(nèi)存都是不再使用的內(nèi)存。因為這些內(nèi)存已經(jīng)丟失了其地址信息,從而導(dǎo)致內(nèi)核不能再使用這些內(nèi)存。

我們來看看下圖的事例:


如上圖所示,指針A原來指向內(nèi)存塊A,但后來指向新申請的內(nèi)存塊B,從而導(dǎo)致內(nèi)存塊A的內(nèi)存地址信息丟失。如果此時用戶沒有及時釋放掉內(nèi)存塊A,就會導(dǎo)致內(nèi)存泄漏。

當然少量的內(nèi)存泄漏并不會造成很嚴重的效果,但如果是頻發(fā)性的內(nèi)存泄漏,將會造成系統(tǒng)內(nèi)存資源耗盡,從而導(dǎo)致系統(tǒng)崩潰。

2. 內(nèi)核中的指針

既然沒有指針引用的內(nèi)存屬于泄漏的內(nèi)存,那么只需要找出系統(tǒng)是否存在沒有指針引用的內(nèi)存,就可以判斷系統(tǒng)是否存在內(nèi)存泄漏。

那么,怎么找到內(nèi)核中的所有指針呢?我們知道,指針一般存放在 內(nèi)核數(shù)據(jù)段、內(nèi)核棧 和 動態(tài)申請的內(nèi)存塊 中。如下圖所示:


但內(nèi)核并沒有對指針進行記錄,也就是說內(nèi)核并不知道這些區(qū)域是否存在指針。那么內(nèi)核只能夠把這些區(qū)域當成是由指針組成的,也就是說把這些區(qū)域中的每個元素都當成是一個指針。如下圖所示:


當然,把所有元素都當成是指針是一個假設(shè),所以會存在誤判的情況。不過這也沒關(guān)系,因為 kmemleak 這個功能只是為了找到內(nèi)核中疑似內(nèi)存泄漏的地方。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ??


3. 記錄動態(tài)內(nèi)存塊

前面說過,kmemleak 機制用于分析由 memblock_alloc、kmalloc、vmalloc、kmem_cache_alloc 等函數(shù)申請的內(nèi)存是否存在泄漏。

分析的依據(jù)是:掃描內(nèi)核中所有的指針,然后判斷這些指針是否指向了由 memblock_alloc、kmalloc、vmalloc、kmem_cache_alloc 等函數(shù)申請的內(nèi)存塊。如果存在沒有指針引用的內(nèi)存塊,那么就表示可能存在內(nèi)存泄漏。

所以,當使用 memblock_alloc、kmalloc、vmalloc、kmem_cache_alloc 等函數(shù)申請內(nèi)存時,內(nèi)核會把申請到的內(nèi)存塊信息記錄下來,用于后續(xù)掃描時使用。內(nèi)核使用 kmemleak_object 對象來記錄這些內(nèi)存塊的信息,然后通過一棵紅黑樹把這些 kmemleak_object 對象組織起來(使用內(nèi)存塊的地址作為鍵),如下圖所示:


所以內(nèi)存泄漏檢測的原理是:

  • 遍歷內(nèi)核中所有的指針,然后從紅黑樹中查找是否存在對應(yīng)的內(nèi)存塊,如果存在就把內(nèi)存塊打上標記。

  • 所有指針掃描完畢后,再遍歷紅黑樹中所有 kmemleak_object 對象。如果發(fā)現(xiàn)沒有打上標記的內(nèi)存塊,說明存在內(nèi)存泄漏(也就是說,存在沒有被指針引用的內(nèi)存塊),并且將對應(yīng)的內(nèi)存塊信息記錄下來。

kmemleak 實現(xiàn)

了解了 kmemleak 機制的原理后,現(xiàn)在我們來分析其代碼實現(xiàn)。

1. kmemleak_object 對象

上面介紹過,內(nèi)核通過 kmemleak_object 對象來記錄動態(tài)內(nèi)存塊的信息,其定義如下:

kmemleak_object 對象的成員字段比較多,現(xiàn)在我們重點關(guān)注 rb_node 、pointer 和 size 這 3 個字段:

  • rb_node:此字段用于將 kmemleak_object 對象連接到紅黑樹中。

  • pointer:用于記錄內(nèi)存塊的起始地址。

  • size:用于記錄內(nèi)存塊的大小。

內(nèi)核就是通過這 3 個字段,把 kmemleak_object 對象連接到全局紅黑樹中。

例如利用 kmalloc 函數(shù)申請內(nèi)存時,最終會調(diào)用 create_object 來創(chuàng)建 kmemleak_object 對象,并且將其添加到全局紅黑樹中。我們來看看 create_obiect 函數(shù)的實現(xiàn),如下:

雖然 create_obiect 函數(shù)的代碼比較長,但是邏輯卻很簡單,主要完成 2 件事情:

  • 申請一個新的 kmemleak_object 對象,并且初始化其各個字段。

  • 將新申請的 kmemleak_object 對象添加到全局紅黑樹中。

將 kmemleak_object 對象插入到全局紅黑樹的算法與數(shù)據(jù)結(jié)構(gòu)中的平衡二叉樹算法是一致的,所以不了解的同學可以查閱相關(guān)的資料。

2. 內(nèi)存泄漏檢測

當開啟內(nèi)存泄漏檢測時,內(nèi)核將會創(chuàng)建一個名為 kmemleak 的內(nèi)核線程來進行檢測。

在分析內(nèi)存檢測的實現(xiàn)之前,我們先來了解一下關(guān)于 kmemleak_object 對象的三個概念:

  • 白色節(jié)點 :表示此對象沒有被指針引用(count 字段少于 min_count 字段)。

  • 灰色節(jié)點 :表示此對象被一個或多個指針引用(count 字段大于或等于 min_count 字段)。

  • 黑色節(jié)點 :表示此對象不需要被掃描(min_count 字段等于 -1)。

接著我們來看看 kmemleak 內(nèi)核線程的實現(xiàn):

可以看出 kmemleak 內(nèi)核線程主要通過調(diào)用 kmemleak_scan 函數(shù)來進行內(nèi)存泄漏掃描。我們繼續(xù)來看看 kmemleak_scan 函數(shù)的實現(xiàn):

由于 kmemleak_scan 函數(shù)的代碼比較長,所以我們對其進行精簡。精簡后可以看出,kmemleak_scan 函數(shù)主要完成 5 件事情:

  • 將系統(tǒng)中所有 kmemleak_object 對象的 count 字段置 0,表示掃描開始時,所有節(jié)點都是白色節(jié)點。

  • 調(diào)用 scan_block 函數(shù)掃描 數(shù)據(jù)段 與 未初始化數(shù)據(jù)段,因為這兩個區(qū)域可能存在指針。

  • 掃描所有 內(nèi)存頁結(jié)構(gòu),這是因為內(nèi)存頁結(jié)構(gòu)可能會引用其他內(nèi)存塊,所以也要對其進行掃描。

  • 掃描所有 進程內(nèi)核棧,由于進程內(nèi)核棧可能存在指針,所以要對其進行掃描。

  • 掃描所有 灰色節(jié)點,由于灰色節(jié)點也可能存在指針,所以要對其進行掃描。

掃描主要通過 scan_block 函數(shù)進行,我們來看看 scan_block 函數(shù)的實現(xiàn):

scan_block 函數(shù)主要完成以下幾個步驟:

  • 遍歷內(nèi)存區(qū)所有指針。

  • 查找指針所引用的內(nèi)存塊是否存在于紅黑樹中,如果不存在就跳過處理此對象。

  • 如果 kmemleak_object 對象不是白色,說明已經(jīng)有指針引用此內(nèi)存塊,跳過處理此對象。

  • 對 kmemleak_object 對象的 count 字段進行加一操作,表示有指針引用此內(nèi)存塊。

  • 判斷當前 kmemleak_object 對象是否是灰色節(jié)點(count 字段大于或等于 min_count 字段),如果是將其添加到灰色節(jié)點鏈表中。

掃描完畢后,所有白色的節(jié)點就是可能存在內(nèi)存泄漏的內(nèi)存塊。


原文作者:Linux內(nèi)核那些事



詳細講解Linux內(nèi)存泄漏檢測實現(xiàn)原理與實現(xiàn)的評論 (共 條)

分享到微博請遵守國家法律
张家界市| 云和县| 乐东| 浦北县| 德阳市| 延边| 江城| 宁河县| 济源市| 西吉县| 沙湾县| 顺平县| 绥芬河市| 广元市| 思南县| 汝州市| 高密市| 集贤县| 泗水县| 金坛市| 甘肃省| 上饶市| 车致| 桦甸市| 资阳市| 佳木斯市| 峨眉山市| 武平县| 鄢陵县| 乌鲁木齐县| 福安市| 安庆市| 汾西县| 梁山县| 阜南县| 龙南县| 鄂尔多斯市| 浦北县| 淮阳县| 康马县| 五家渠市|