日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

linux pmap 内存泄露,一个驱动导致的内存泄漏问题的分析过程(meminfo-pmap-slabtop-alloc_calls)...

發(fā)布時(shí)間:2025/3/12 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux pmap 内存泄露,一个驱动导致的内存泄漏问题的分析过程(meminfo-pmap-slabtop-alloc_calls)... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)鍵詞:sqllite、meminfo、slabinfo、alloc_calls、nand、SUnreclaim等等。

下面記錄一個(gè)由于驅(qū)動(dòng)導(dǎo)致的內(nèi)存泄漏問(wèn)題分析過(guò)程。

首先介紹問(wèn)題背景,在一款嵌入式設(shè)備上,新使用sqllite庫(kù)進(jìn)行數(shù)據(jù)庫(kù)操作,在操作數(shù)據(jù)(大量讀寫(xiě)操作)一段時(shí)間之后,發(fā)生OOM現(xiàn)象。

然后OOM會(huì)選擇進(jìn)程kill,即使系統(tǒng)中不剩什么進(jìn)程,仍然內(nèi)存緊張。

下面就介紹從上往下查找問(wèn)題,然后在底層掐住RootCause,進(jìn)而解決問(wèn)題的分析過(guò)程。

1. 問(wèn)題初步分析

首先懷疑的是sqllite庫(kù)問(wèn)題,在PC進(jìn)行同樣的測(cè)試未發(fā)現(xiàn)內(nèi)存泄漏。在另一款參考設(shè)備上,進(jìn)行同樣的測(cè)試,未發(fā)現(xiàn)內(nèi)存泄漏。

以上測(cè)試確保了測(cè)試程序、sqllite庫(kù)等一致,僅交叉工具鏈和平臺(tái)不一致。

結(jié)論:可以基本肯定sqllite庫(kù)以及測(cè)試程序沒(méi)有問(wèn)題,可能的問(wèn)題包括交叉工具鏈、平臺(tái)問(wèn)題。平臺(tái)問(wèn)題更大,所以問(wèn)題集中到具體平臺(tái)上進(jìn)行分析。

疑問(wèn)點(diǎn):

1. 為何進(jìn)程退出后,泄漏的內(nèi)存沒(méi)有釋放?參見(jiàn)分析,是因?yàn)镾Unreclaim的slab內(nèi)存不在進(jìn)程內(nèi)存統(tǒng)計(jì)范圍之內(nèi)。

2. 是否由于工具鏈不同導(dǎo)致庫(kù)函數(shù)表現(xiàn)不一致?參見(jiàn)分析1,內(nèi)存泄漏點(diǎn)在內(nèi)核驅(qū)動(dòng)中。?參見(jiàn)分析2,經(jīng)過(guò)在RAM上運(yùn)行sqllite測(cè)試;單獨(dú)測(cè)試NAND文件系統(tǒng),得出泄漏和sqllite無(wú)關(guān)。

3. 是平臺(tái)內(nèi)核導(dǎo)致的泄漏嗎?參見(jiàn)分析,確定泄漏在kmalloc-4096這個(gè)slab中。

2. 具體平臺(tái)查找內(nèi)存泄漏方向

定位內(nèi)存泄漏按照從大到小的思路,即首先看系統(tǒng)內(nèi)存哪里泄漏,然后再看進(jìn)程內(nèi)存哪里泄漏,最后看哪種內(nèi)存泄漏。

2.1 分析系統(tǒng)內(nèi)存

首先通過(guò)cat /proc/meminfo,然后分析泄漏點(diǎn)。

從MemFree和MemAvailable看,內(nèi)存將低了235M和228M。

然后看一下下面內(nèi)存消耗在哪里?可以看出slab消耗了228M,再細(xì)節(jié)可以看出SUreclaim消耗了228M。基本確定

結(jié)論:確定由于Unreclaim類(lèi)型的slab泄漏導(dǎo)致的內(nèi)存泄漏。

疑問(wèn)點(diǎn):找出具體哪個(gè)slab泄漏了?參見(jiàn)分析,在kmalloc-4096這個(gè)slab中。?哪個(gè)調(diào)用的slab申請(qǐng)?參見(jiàn)分析,通過(guò)kmalloc-4096的alloc_calls可以知道調(diào)用點(diǎn)。

2.2 分析進(jìn)程內(nèi)存

通過(guò)pmap -X -p `pidof xxx`來(lái)獲取進(jìn)程的地址映射空間,可以分析進(jìn)程內(nèi)存細(xì)節(jié)。

結(jié)論:通過(guò)下面的對(duì)比,可以看出進(jìn)程本身沒(méi)有導(dǎo)致內(nèi)存泄漏。所以?xún)?nèi)存泄漏雖然有此進(jìn)程導(dǎo)致,但是泄漏點(diǎn)不在進(jìn)程中。

2.3 分析slab內(nèi)存泄漏點(diǎn)

既然確定slab導(dǎo)致的泄漏,那么就需要使用slabtop、/proc/slabinfo以及/sys/kernel/slab來(lái)分析。

從下面可以看出泄漏點(diǎn)在kmalloc-4096這個(gè)slab,這個(gè)slab消耗的內(nèi)存為250M左右。

然后就是去找slab的調(diào)用記錄,幸運(yùn)的是系統(tǒng)在/sys/kernel/slab/*/中提供了alloc_calls和free_calls。

alloc_calls:

1 pidmap_init+0x4e/0x10c age=418000 pid=0

1 con_init+0xf6/0x21c age=418007 pid=0

1 pcpu_mem_zalloc+0x36/0x74 age=417641 pid=1

1 seq_buf_alloc+0x26/0x54 age=0 pid=349

1 register_leaf_sysctl_tables+0x74/0x1b0 age=418000 pid=0

1 ubifs_mount+0x68/0x15e8 age=416589 pid=1

1 ubifs_mount+0xdaa/0x15e8 age=416588 pid=1

1 nand_scan_tail+0xa2/0x6a8 age=417469 pid=1

1 ubi_attach_mtd_dev+0x9a/0xc38 age=417168 pid=1

1 sourcesink_bind+0x382/0x4c0 age=417588 pid=1

1 vid_dev_probe+0x32/0x1a0 age=417569 pid=1

2 hantrodec_probe+0x56/0x944 age=417502/417512/417523 pid=1

55898 spinand_cmdfunc+0x236/0x52c age=8997/225988/416514 pid=1-202 1 flow_cache_cpu_prepare.isra.7+0x3c/0x74 age=417889 pid=1

free_calls:

55840 age=343019 pid=0

59 kvfree+0x2a/0x60 age=0/239003/415431 pid=140-349

1 ubifs_read_superblock+0x690/0xe14 age=416600 pid=1

8 kobject_uevent_env+0xda/0x580 age=416605/417396/417653 pid=1

3 uevent_show+0x5e/0xf4 age=409638/411302/413798 pid=143-150

1 skb_free_head+0x2c/0x6c age=417902 pid=1

結(jié)論:從alloc_calls可以看出spinand_cmdfunc中申請(qǐng)了55898次slab,和系統(tǒng)內(nèi)存泄漏量基本一致。

2.4 分析驅(qū)動(dòng)內(nèi)存泄漏

通過(guò)objdump -S -l -D vmlinux > vmlinux.txt,然后結(jié)合反匯編代碼,找到spinand_cmdfunc+0x236可以找到具體點(diǎn)。

805829e2: e3f26433 bsr 0x803cf248 //803cf248 <_end>

805829e6: c4004820 lsli r0, r0, 0spinand_cmdfunc():/home/al/deepeye1000/linux/drivers/staging/mt29f_spinand/mt29f_spinand.c:806spinand_program_page(info->spi, state->row, state->col,

所以問(wèn)題最終指向了mt29f_spinand.c的806行,spinand_program_page()這個(gè)函數(shù)里面。

分析此驅(qū)動(dòng)代碼,可以看出通過(guò)devm_kzalloc()申請(qǐng)的內(nèi)存沒(méi)有被釋放的點(diǎn)。雖然此內(nèi)存在模塊卸載的時(shí)候會(huì)被自動(dòng)釋放,但是NAND驅(qū)動(dòng)一般不會(huì)被卸載。

結(jié)論:確定泄漏點(diǎn)在spinand_program_page()中。

3. 旁證測(cè)試

基本上找到的問(wèn)題點(diǎn),為了驗(yàn)證上述分析做了幾個(gè)簡(jiǎn)單的測(cè)試。

3.1 在ramfs中進(jìn)行sqllite數(shù)據(jù)庫(kù)操作

既然泄漏點(diǎn)在NAND驅(qū)動(dòng)中,那么避開(kāi)在NAND中進(jìn)行讀寫(xiě)操作即可。在/tmp目錄下,進(jìn)行數(shù)據(jù)庫(kù)操作,作為對(duì)比測(cè)試。

同樣的軟件和平臺(tái)下,運(yùn)行同樣的業(yè)務(wù)。

結(jié)論:在ramfs中進(jìn)行操作,沒(méi)有發(fā)生內(nèi)存泄漏。說(shuō)明泄漏sqllite操作無(wú)關(guān)。。

3.2 在NAND上進(jìn)行文件cp、rm等操作

既然泄漏點(diǎn)在NAND,那么不使用數(shù)據(jù)庫(kù)讀寫(xiě),純文件系統(tǒng)讀寫(xiě)如何呢?

經(jīng)過(guò)測(cè)試,同樣發(fā)現(xiàn)SUreclaim內(nèi)存增加導(dǎo)致的泄漏。

結(jié)論:內(nèi)存泄漏跟NAND上文件操作有關(guān)。

為什么之前沒(méi)有發(fā)現(xiàn)內(nèi)存泄漏問(wèn)題呢?原來(lái)主要業(yè)務(wù)是運(yùn)行應(yīng)用,很少對(duì)NAND進(jìn)行寫(xiě),即使有寫(xiě)也是偶爾的,發(fā)現(xiàn)不了內(nèi)存泄漏。這種情況在頻繁的讀寫(xiě)、刪除操作下比較容易復(fù)現(xiàn)。

4. 解決問(wèn)題

解決的思路就是確保在函數(shù)退出的時(shí)候,保證wbuf的內(nèi)存能夠得到釋放。

diff--git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c

index 2474d88..7042934 100644

--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c

@@-495,7 +495,8 @@ static int spinand_program_page(struct spi_device *spi_nand,

#ifdef CONFIG_MTD_SPINAND_ONDIEECC

unsignedinti, j;- wbuf = devm_kzalloc(&spi_nand->dev, CACHE_BUF, GFP_KERNEL);

+ wbuf = kzalloc(CACHE_BUF, GFP_KERNEL);if (!wbuf)return -ENOMEM;

@@-509,7 +510,7 @@ static int spinand_program_page(struct spi_device *spi_nand,

retval=spinand_enable_ecc(spi_nand);if (retval < 0) {

dev_err(&spi_nand->dev, "enable ecc failed!!");- return retval;

+ gotoexit;

}

}#else...

-

- return 0;

+exit:

+#ifdef CONFIG_MTD_SPINAND_ONDIEECC

+ kfree(wbuf);

+#endif

+ returnretval;

}

5. 驗(yàn)證測(cè)試

基于以上的分析過(guò)程,構(gòu)建測(cè)試用例:

1. 進(jìn)行同樣的NAND上sqllite數(shù)據(jù)操作

2. 同樣重復(fù)cp、rm操作NAND上文件系統(tǒng)

總結(jié)

以上是生活随笔為你收集整理的linux pmap 内存泄露,一个驱动导致的内存泄漏问题的分析过程(meminfo-pmap-slabtop-alloc_calls)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。