MOCOR平臺(tái)內(nèi)存管理介紹及案例分析課件_第1頁(yè)
MOCOR平臺(tái)內(nèi)存管理介紹及案例分析課件_第2頁(yè)
MOCOR平臺(tái)內(nèi)存管理介紹及案例分析課件_第3頁(yè)
MOCOR平臺(tái)內(nèi)存管理介紹及案例分析課件_第4頁(yè)
MOCOR平臺(tái)內(nèi)存管理介紹及案例分析課件_第5頁(yè)
已閱讀5頁(yè),還剩63頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、MOCOR平臺(tái)內(nèi)存管理介紹及案 例分析 保密信息 . 22021-7-12 MOCOR平臺(tái)內(nèi)存管理介紹平臺(tái)內(nèi)存管理介紹 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) ThreadX的內(nèi)存管理的內(nèi)存管理 MOCOR的內(nèi)存管理的內(nèi)存管理 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 保密信息 . 32021-7-12 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) 一般的嵌入式系統(tǒng)中最基本的內(nèi)存管理方案有兩種一般的嵌入式系統(tǒng)中最基本的內(nèi)存管理方案有兩種靜態(tài)分配靜態(tài)分配 和動(dòng)態(tài)分配。和動(dòng)態(tài)分配。 靜態(tài)分配是指在編譯或鏈接時(shí)將程序所需的內(nèi)存空間分配好。采靜態(tài)分配是指在編譯或鏈接時(shí)將程序所需的內(nèi)存空間分配

2、好。采 用這種分配方案的內(nèi)存段,其大小一般在編譯時(shí)就能夠確定。靜用這種分配方案的內(nèi)存段,其大小一般在編譯時(shí)就能夠確定。靜 態(tài)分配比較簡(jiǎn)單,一般不需要特殊的管理。態(tài)分配比較簡(jiǎn)單,一般不需要特殊的管理。 動(dòng)態(tài)分配是指系統(tǒng)運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)地分配內(nèi)存,為實(shí)現(xiàn)動(dòng)態(tài)動(dòng)態(tài)分配是指系統(tǒng)運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)地分配內(nèi)存,為實(shí)現(xiàn)動(dòng)態(tài) 分配,系統(tǒng)里需要有一套完善的管理機(jī)制。本文中所指的內(nèi)存管分配,系統(tǒng)里需要有一套完善的管理機(jī)制。本文中所指的內(nèi)存管 理,就是指動(dòng)態(tài)分配內(nèi)存的管理。理,就是指動(dòng)態(tài)分配內(nèi)存的管理。 保密信息 . 42021-7-12 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) MOCOR內(nèi)存管理體系的一

3、個(gè)大致的調(diào)用層次如下圖所示:內(nèi)存管理體系的一個(gè)大致的調(diào)用層次如下圖所示: 保密信息 . 52021-7-12 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) 從可用的內(nèi)存資源的角度,還可以得到下面的一個(gè)內(nèi)存分配圖。從可用的內(nèi)存資源的角度,還可以得到下面的一個(gè)內(nèi)存分配圖。 保密信息 . 62021-7-12 MOCOR平臺(tái)內(nèi)存管理介紹平臺(tái)內(nèi)存管理介紹 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) ThreadX的內(nèi)存管理的內(nèi)存管理 MOCOR的內(nèi)存管理的內(nèi)存管理 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 保密信息 . 72021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理 內(nèi)存字節(jié)池(內(nèi)存字

4、節(jié)池(BTYE POOL) 內(nèi)存塊池(內(nèi)存塊池(BLOCK POOL) 保密信息 . 82021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理 內(nèi)存字節(jié)池(內(nèi)存字節(jié)池(BTYE POOL) 保密信息 . 92021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存字節(jié)池內(nèi)存字節(jié)池 u1.基本概念:基本概念: 內(nèi)存字節(jié)池是一個(gè)連續(xù)的內(nèi)存塊。在字節(jié)池中,內(nèi)存的分配以字節(jié)為單位,任意大小內(nèi)存字節(jié)池是一個(gè)連續(xù)的內(nèi)存塊。在字節(jié)池中,內(nèi)存的分配以字節(jié)為單位,任意大小 的內(nèi)存都可以在字節(jié)池上分配(受限于內(nèi)存的容量)。的內(nèi)存都可以在字節(jié)池上分配(受限于內(nèi)存的容量)。 內(nèi)存字節(jié)池類(lèi)似于內(nèi)存字節(jié)池類(lèi)似于C語(yǔ)言里

5、的堆語(yǔ)言里的堆(heap),所以,字節(jié)池我們也可以把它叫做字節(jié)堆,所以,字節(jié)池我們也可以把它叫做字節(jié)堆, 代碼里我們也可以看到創(chuàng)建的字節(jié)池通常以代碼里我們也可以看到創(chuàng)建的字節(jié)池通常以heap來(lái)命名。但與一般意義上的堆的不來(lái)命名。但與一般意義上的堆的不 同在于,同在于,ThreadX里的字節(jié)池可以有多個(gè),里的字節(jié)池可以有多個(gè),MOCOR平臺(tái)也是利用了這一特性,根據(jù)平臺(tái)也是利用了這一特性,根據(jù) 不同的需求而創(chuàng)建了多個(gè)不同的需求而創(chuàng)建了多個(gè)heap。 每一個(gè)字節(jié)池都有一個(gè)相應(yīng)的字節(jié)池控制塊,通常是一個(gè)全局結(jié)構(gòu)。控制塊包括對(duì)內(nèi)每一個(gè)字節(jié)池都有一個(gè)相應(yīng)的字節(jié)池控制塊,通常是一個(gè)全局結(jié)構(gòu)??刂茐K包括對(duì)內(nèi)

6、存池的定義和狀態(tài),比如內(nèi)存池的名字,可用的字節(jié)數(shù)等。該結(jié)構(gòu)的定義如下:存池的定義和狀態(tài),比如內(nèi)存池的名字,可用的字節(jié)數(shù)等。該結(jié)構(gòu)的定義如下: 保密信息 . 102021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存字節(jié)池內(nèi)存字節(jié)池 保密信息 . 112021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存字節(jié)池內(nèi)存字節(jié)池 u2.分配方式:分配方式: 從字節(jié)池中分配內(nèi)存類(lèi)似于從字節(jié)池中分配內(nèi)存類(lèi)似于C語(yǔ)言的語(yǔ)言的malloc調(diào)用,該調(diào)用返回所需內(nèi)存的數(shù)量(以字調(diào)用,該調(diào)用返回所需內(nèi)存的數(shù)量(以字 節(jié)為單位)。分配的原則是節(jié)為單位)。分配的原則是“首次符合首次符合”原則,就是說(shuō),當(dāng)?shù)谝粋€(gè)

7、空閑內(nèi)存塊的大小原則,就是說(shuō),當(dāng)?shù)谝粋€(gè)空閑內(nèi)存塊的大小 滿(mǎn)足需求時(shí),就從該內(nèi)存塊分配內(nèi)存,然后將該內(nèi)存塊的剩余內(nèi)存轉(zhuǎn)換成一個(gè)新塊。滿(mǎn)足需求時(shí),就從該內(nèi)存塊分配內(nèi)存,然后將該內(nèi)存塊的剩余內(nèi)存轉(zhuǎn)換成一個(gè)新塊。 字節(jié)池在初始狀態(tài)下,只有一個(gè)空閑塊,以后隨著隨著分配的進(jìn)行,內(nèi)存塊會(huì)隨之增字節(jié)池在初始狀態(tài)下,只有一個(gè)空閑塊,以后隨著隨著分配的進(jìn)行,內(nèi)存塊會(huì)隨之增 多。多。 除了上述的分配原則之外,字節(jié)池里還定義了一個(gè)值除了上述的分配原則之外,字節(jié)池里還定義了一個(gè)值BYTE_POOL_SLIP_SIZE。這。這 是在代碼里實(shí)現(xiàn)指定的一個(gè)具體數(shù)值,在分配內(nèi)存時(shí),如果要分配的內(nèi)存大小大于這是在代碼里實(shí)現(xiàn)指定的

8、一個(gè)具體數(shù)值,在分配內(nèi)存時(shí),如果要分配的內(nèi)存大小大于這 一數(shù)值,則從字節(jié)池的底部開(kāi)始分配。采用這種分配方式是為了減少內(nèi)存碎片的產(chǎn)生,一數(shù)值,則從字節(jié)池的底部開(kāi)始分配。采用這種分配方式是為了減少內(nèi)存碎片的產(chǎn)生, 盡量把大內(nèi)存的分配區(qū)域和小內(nèi)存的分配區(qū)域分開(kāi)。目前系統(tǒng)里定義的盡量把大內(nèi)存的分配區(qū)域和小內(nèi)存的分配區(qū)域分開(kāi)。目前系統(tǒng)里定義的 BYTE_POOL_SLIP_SIZE為為80K。 保密信息 . 122021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存字節(jié)池內(nèi)存字節(jié)池 u3.內(nèi)存布局:內(nèi)存布局: 以一個(gè)分配了兩次的字節(jié)池為例,在內(nèi)存中的情況如下:以一個(gè)分配了兩次的字節(jié)池為例,在內(nèi)存中

9、的情況如下: 保密信息 . 132021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存字節(jié)池內(nèi)存字節(jié)池 注意:注意: 首先要注意的問(wèn)題是碎片,一個(gè)字節(jié)池可能有首先要注意的問(wèn)題是碎片,一個(gè)字節(jié)池可能有2000字節(jié)的可用空間,字節(jié)的可用空間, 但不保證一定能分配到但不保證一定能分配到2000字節(jié)的連續(xù)空間,內(nèi)存池對(duì)連續(xù)字節(jié)的字節(jié)的連續(xù)空間,內(nèi)存池對(duì)連續(xù)字節(jié)的 數(shù)量不做保證。數(shù)量不做保證。 分配一塊內(nèi)存所需要的時(shí)間跟分配內(nèi)存的大小,字節(jié)池中的碎片數(shù)分配一塊內(nèi)存所需要的時(shí)間跟分配內(nèi)存的大小,字節(jié)池中的碎片數(shù) 等因素有關(guān),如果字節(jié)池有等因素有關(guān),如果字節(jié)池有2000字節(jié)的空閑塊,花多長(zhǎng)時(shí)間找到這字

10、節(jié)的空閑塊,花多長(zhǎng)時(shí)間找到這 塊內(nèi)存也是沒(méi)有保證的。因此,在時(shí)間要求苛刻的任務(wù)中應(yīng)避免使塊內(nèi)存也是沒(méi)有保證的。因此,在時(shí)間要求苛刻的任務(wù)中應(yīng)避免使 用字節(jié)池。用字節(jié)池。 字節(jié)池不能在中斷函數(shù)里使用,也不能在字節(jié)池不能在中斷函數(shù)里使用,也不能在timer回調(diào)函數(shù)里使用?;卣{(diào)函數(shù)里使用。 保密信息 . 142021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存字節(jié)池內(nèi)存字節(jié)池 思考:思考: 假定系統(tǒng)中有一個(gè)內(nèi)存字節(jié)池,并且已經(jīng)從中分配了幾次假定系統(tǒng)中有一個(gè)內(nèi)存字節(jié)池,并且已經(jīng)從中分配了幾次 內(nèi)存。當(dāng)內(nèi)存池中還有內(nèi)存。當(dāng)內(nèi)存池中還有500字節(jié)的剩余內(nèi)存時(shí),應(yīng)用程序申字節(jié)的剩余內(nèi)存時(shí),應(yīng)用程序申

11、 請(qǐng)請(qǐng)200字節(jié)的內(nèi)存,在什么情況下,這樣的申請(qǐng)不能滿(mǎn)足?字節(jié)的內(nèi)存,在什么情況下,這樣的申請(qǐng)不能滿(mǎn)足? 保密信息 . 152021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理 內(nèi)存塊池(內(nèi)存塊池(BLOCK POOL) 保密信息 . 162021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存塊池內(nèi)存塊池 u1.基本概念:基本概念: 內(nèi)存塊池也是一個(gè)連續(xù)的字節(jié)塊,但它是由一定數(shù)量的固定內(nèi)存塊池也是一個(gè)連續(xù)的字節(jié)塊,但它是由一定數(shù)量的固定szie的內(nèi)存塊組成的。因的內(nèi)存塊組成的。因 此,從一個(gè)內(nèi)存塊池中分配出的內(nèi)存總是固定大小的。此,從一個(gè)內(nèi)存塊池中分配出的內(nèi)存總是固定大小的。 相比字節(jié)

12、池,內(nèi)存塊池的兩個(gè)主要優(yōu)勢(shì)是:相比字節(jié)池,內(nèi)存塊池的兩個(gè)主要優(yōu)勢(shì)是: 沒(méi)有碎片。因?yàn)閮?nèi)存塊池是固定沒(méi)有碎片。因?yàn)閮?nèi)存塊池是固定size的塊構(gòu)成,所以沒(méi)有碎片的產(chǎn)生。的塊構(gòu)成,所以沒(méi)有碎片的產(chǎn)生。 分配和釋放的速度很快。所需的時(shí)間相當(dāng)于簡(jiǎn)單的鏈表操作,分配時(shí)不需要搜索整個(gè)分配和釋放的速度很快。所需的時(shí)間相當(dāng)于簡(jiǎn)單的鏈表操作,分配時(shí)不需要搜索整個(gè) 內(nèi)存塊列表,它總是使用鏈表頭部的內(nèi)存塊來(lái)分配。內(nèi)存塊列表,它總是使用鏈表頭部的內(nèi)存塊來(lái)分配。 內(nèi)存塊池的主要缺點(diǎn)是缺乏靈活性。固定尺寸既是它的優(yōu)點(diǎn)也是它的缺點(diǎn)。如果一個(gè)內(nèi)存塊池的主要缺點(diǎn)是缺乏靈活性。固定尺寸既是它的優(yōu)點(diǎn)也是它的缺點(diǎn)。如果一個(gè) 內(nèi)存塊池的

13、尺寸足夠大,可以滿(mǎn)足用戶(hù)最極限的內(nèi)存分配需求,那么,這個(gè)內(nèi)存塊池內(nèi)存塊池的尺寸足夠大,可以滿(mǎn)足用戶(hù)最極限的內(nèi)存分配需求,那么,這個(gè)內(nèi)存塊池 上分配許多不同尺寸的內(nèi)存會(huì)導(dǎo)致嚴(yán)重的內(nèi)存浪費(fèi)。一種解決辦法是同時(shí)創(chuàng)建幾個(gè)不上分配許多不同尺寸的內(nèi)存會(huì)導(dǎo)致嚴(yán)重的內(nèi)存浪費(fèi)。一種解決辦法是同時(shí)創(chuàng)建幾個(gè)不 同的內(nèi)存塊池,每個(gè)內(nèi)存塊池分別容納不同尺寸的內(nèi)存塊。目前同的內(nèi)存塊池,每個(gè)內(nèi)存塊池分別容納不同尺寸的內(nèi)存塊。目前MOCOR平臺(tái)就是這平臺(tái)就是這 樣做的,具體我們后面再討論。樣做的,具體我們后面再討論。 同字節(jié)池一樣,內(nèi)存塊池也有一個(gè)控制塊結(jié)構(gòu),其中有該內(nèi)存塊的相關(guān)信息,該結(jié)構(gòu)同字節(jié)池一樣,內(nèi)存塊池也有一個(gè)控制

14、塊結(jié)構(gòu),其中有該內(nèi)存塊的相關(guān)信息,該結(jié)構(gòu) 如下:如下: 保密信息 . 172021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存塊池內(nèi)存塊池 保密信息 . 182021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存塊池內(nèi)存塊池 u2.分配方式:分配方式: 內(nèi)存塊池中分配內(nèi)存是非??斓?,主要得益于內(nèi)存塊池中的所有空閑內(nèi)存塊組成一個(gè)內(nèi)存塊池中分配內(nèi)存是非??斓模饕靡嬗趦?nèi)存塊池中的所有空閑內(nèi)存塊組成一個(gè) 鏈表鏈表(即上面結(jié)構(gòu)中的即上面結(jié)構(gòu)中的tx_block_pool_available_list)。每次分配時(shí)只需要取鏈表頭即。每次分配時(shí)只需要取鏈表頭即 可,無(wú)須遍歷內(nèi)存塊池來(lái)找到空

15、閑塊??桑瑹o(wú)須遍歷內(nèi)存塊池來(lái)找到空閑塊。 保密信息 . 192021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存塊池內(nèi)存塊池 u3.內(nèi)存布局:內(nèi)存布局: 保密信息 . 202021-7-12 ThreadX的內(nèi)存管理的內(nèi)存管理-內(nèi)存塊池內(nèi)存塊池 思考思考 如何計(jì)算一個(gè)內(nèi)存塊池所占用的物理內(nèi)存大小如何計(jì)算一個(gè)內(nèi)存塊池所占用的物理內(nèi)存大小? 保密信息 . 212021-7-12 MOCOR平臺(tái)內(nèi)存管理介紹平臺(tái)內(nèi)存管理介紹 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) ThreadX的內(nèi)存管理的內(nèi)存管理 MOCOR的內(nèi)存管理的內(nèi)存管理 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 保密信息 .

16、 222021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 MOCOR平臺(tái)在平臺(tái)在ThreadX內(nèi)存管理的基礎(chǔ)上,又做了進(jìn)一步的封裝,內(nèi)存管理的基礎(chǔ)上,又做了進(jìn)一步的封裝, 這樣可以更便于上層應(yīng)用調(diào)用。前面我們已經(jīng)了解了這樣可以更便于上層應(yīng)用調(diào)用。前面我們已經(jīng)了解了ThreadX是如是如 何對(duì)內(nèi)存進(jìn)行管理的,下面我們從底層來(lái)到上層,看一看何對(duì)內(nèi)存進(jìn)行管理的,下面我們從底層來(lái)到上層,看一看MOCOR是是 如何利用如何利用Threadx的內(nèi)存管理機(jī)制來(lái)建立自己的內(nèi)存管理方式。的內(nèi)存管理機(jī)制來(lái)建立自己的內(nèi)存管理方式。 之之 前的前的MOCOR文檔里,將內(nèi)存字節(jié)池稱(chēng)為堆(文檔里,將內(nèi)存字節(jié)池稱(chēng)為堆(heap

17、),而將內(nèi)存塊),而將內(nèi)存塊 池稱(chēng)為內(nèi)存池(池稱(chēng)為內(nèi)存池(pool),我們也延續(xù)這種說(shuō)法,請(qǐng)注意不要混淆。我們也延續(xù)這種說(shuō)法,請(qǐng)注意不要混淆。 保密信息 . 232021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 u1.堆內(nèi)存堆內(nèi)存(heap)管理管理: MOCOR平臺(tái)的堆內(nèi)存就是前面講到的內(nèi)存字節(jié)池。最早的平臺(tái)的堆內(nèi)存就是前面講到的內(nèi)存字節(jié)池。最早的MOCOR平臺(tái)只有一個(gè)內(nèi)平臺(tái)只有一個(gè)內(nèi) 存堆,但在實(shí)際使用中發(fā)現(xiàn),程序運(yùn)行時(shí)往往要交錯(cuò)的分配一些動(dòng)態(tài)內(nèi)存和常駐內(nèi)存,存堆,但在實(shí)際使用中發(fā)現(xiàn),程序運(yùn)行時(shí)往往要交錯(cuò)的分配一些動(dòng)態(tài)內(nèi)存和常駐內(nèi)存, 這樣會(huì)產(chǎn)生很多無(wú)法消除的內(nèi)存碎片。同時(shí)這樣會(huì)產(chǎn)生很多無(wú)法

18、消除的內(nèi)存碎片。同時(shí)base等通訊模塊同上層應(yīng)用又是并發(fā)的,等通訊模塊同上層應(yīng)用又是并發(fā)的, 這樣無(wú)規(guī)律的分配也會(huì)造成很多內(nèi)存碎片。為了解決這種情況,后來(lái)這樣無(wú)規(guī)律的分配也會(huì)造成很多內(nèi)存碎片。為了解決這種情況,后來(lái)MOCOR版本將版本將 內(nèi)存堆分成了三塊,也就是創(chuàng)建了三個(gè)內(nèi)存字節(jié)池作為內(nèi)存堆分成了三塊,也就是創(chuàng)建了三個(gè)內(nèi)存字節(jié)池作為heap。這三個(gè)字節(jié)池的分別。這三個(gè)字節(jié)池的分別 是:是:dynamic base heap,static heap和和dynamic app heap。同樣,對(duì)應(yīng)著三個(gè)。同樣,對(duì)應(yīng)著三個(gè) heap也有三個(gè)不同的接口,分別是也有三個(gè)不同的接口,分別是: SCI_AL

19、LOC_BASE, SCI_ALLOC_CONST SCI_ALLOC_APP。 保密信息 . 242021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 三個(gè)三個(gè)heap: Base heap: 主要給主要給PS,Layer1等使用。這個(gè)等使用。這個(gè)heap我們我們 一般不用關(guān)心。一般不用關(guān)心。 Static heap:主要用于分配常駐的內(nèi)存,即一旦分配就:主要用于分配常駐的內(nèi)存,即一旦分配就 不再釋放的內(nèi)存。不再釋放的內(nèi)存。 App heap: 其他不屬于以上兩種情況的內(nèi)存都在這里分其他不屬于以上兩種情況的內(nèi)存都在這里分 配。配。 保密信息 . 252021-7-12 MOCOR內(nèi)存管理內(nèi)存管理

20、三個(gè)三個(gè)heap的大小都定義在的大小都定義在mem_cfg.c里:里: #define MAX_STATIC_HEAP_SIZE (600*1024) #define MAX_DYNAMIC_BASE_HEAP_SIZE (60*1024) #define MAX_DYNAMIC_APP_HEAP_SIZE (1430 * 1024) #define BYTE_HEAP_SIZE (MAX_STATIC_HEAP_SIZE + MAX_DYNAMIC_BASE_HEAP_SIZE + MAX_DYNAMIC_APP_HEAP_SIZE) 保密信息 . 262021-7-12 MOCOR內(nèi)存管理

21、內(nèi)存管理 系統(tǒng)系統(tǒng)assert之后,選擇菜單之后,選擇菜單5,可以看到所有,可以看到所有heap上的內(nèi)存分配信息,上的內(nèi)存分配信息, 類(lèi)似這樣:類(lèi)似這樣: 保密信息 . 272021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 思考:思考: 前面講了前面講了MOCOR里有三個(gè)不同用途的里有三個(gè)不同用途的heap,想一想哪些內(nèi)存是要在,想一想哪些內(nèi)存是要在 static heap里分配的,如果這些內(nèi)存改在里分配的,如果這些內(nèi)存改在app heap上會(huì)有什么問(wèn)題?上會(huì)有什么問(wèn)題? 嘗試舉出幾個(gè)實(shí)際的例子來(lái)說(shuō)明。嘗試舉出幾個(gè)實(shí)際的例子來(lái)說(shuō)明。 保密信息 . 282021-7-12 MOCOR內(nèi)存管理內(nèi)存管

22、理 u2.內(nèi)存池管理:內(nèi)存池管理: 這個(gè)所說(shuō)的內(nèi)存池這個(gè)所說(shuō)的內(nèi)存池(pool)就是特指前面提到的內(nèi)存塊池。之前我們提到過(guò),為了避免浪費(fèi)內(nèi)存,就是特指前面提到的內(nèi)存塊池。之前我們提到過(guò),為了避免浪費(fèi)內(nèi)存, 通常是分配多個(gè)內(nèi)存池,分別對(duì)應(yīng)不同的大小。通常是分配多個(gè)內(nèi)存池,分別對(duì)應(yīng)不同的大小。MOCOR平臺(tái)一共創(chuàng)建了平臺(tái)一共創(chuàng)建了12個(gè)內(nèi)存池,其對(duì)應(yīng)的個(gè)內(nèi)存池,其對(duì)應(yīng)的 大小和包含的內(nèi)存塊的數(shù)目都定義在大小和包含的內(nèi)存塊的數(shù)目都定義在mem_cfg.c里:里: #define POOL_1_BLOCK_SIZE 16 /pools block size #define POOL_1_BLOCK_N

23、UM 480 /pools block number #define POOL_2_BLOCK_SIZE 24 /pools block size #define POOL_2_BLOCK_NUM 320 /pools block number #define POOL_3_BLOCK_SIZE 40 /pools block size #define POOL_3_BLOCK_NUM 650 /pools block number #define POOL_4_BLOCK_SIZE 60 /pools block size #define POOL_4_BLOCK_NUM 500 /pool

24、s block number #define POOL_5_BLOCK_SIZE 112 /pools block size #define POOL_5_BLOCK_NUM 80 /pools block number #define POOL_6_BLOCK_SIZE 180 /pools block size #define POOL_6_BLOCK_NUM 280 /pools block number #define POOL_7_BLOCK_SIZE 300 /pools block size #define POOL_7_BLOCK_NUM 80 /pools block num

25、ber #define POOL_8_BLOCK_SIZE 600 /pools block size #define POOL_8_BLOCK_NUM 120 /pools block number #define POOL_9_BLOCK_SIZE 800 /pools block size #define POOL_9_BLOCK_NUM 100 /pools block number #define POOL_A_BLOCK_SIZE 1100 /pools block size #define POOL_A_BLOCK_NUM 98 /pools block number #defi

26、ne POOL_B_BLOCK_SIZE 1300 /pools block size #define POOL_B_BLOCK_NUM 10 /pools block number #define POOL_C_BLOCK_SIZE 1600 /pools block size #define POOL_C_BLOCK_NUM 12 /pools block number (以上的定義不同版本的以上的定義不同版本的MOCOR可能并不一致,經(jīng)常會(huì)有調(diào)整可能并不一致,經(jīng)常會(huì)有調(diào)整) 保密信息 . 292021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 什么時(shí)候在什么時(shí)候在heap上分配,什么時(shí)候在內(nèi)

27、存池上分配?上分配,什么時(shí)候在內(nèi)存池上分配? MOCOR對(duì)分配內(nèi)存的位置有如下的約定:只有分配的內(nèi)存的大小超對(duì)分配內(nèi)存的位置有如下的約定:只有分配的內(nèi)存的大小超 過(guò)過(guò)mem_cfg.c里定義的最大的內(nèi)存塊池的大小,內(nèi)存才會(huì)在里定義的最大的內(nèi)存塊池的大小,內(nèi)存才會(huì)在heap里里 分配,否則就在內(nèi)存塊池里分配。目前分配,否則就在內(nèi)存塊池里分配。目前MOCOR平臺(tái)定義的最大的內(nèi)平臺(tái)定義的最大的內(nèi) 存塊池是存塊池是1600字節(jié),也就是大于字節(jié),也就是大于1600字節(jié)的內(nèi)存才在字節(jié)的內(nèi)存才在heap里分配。里分配。 保密信息 . 302021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 MOCOR在內(nèi)存池上的

28、分配策略是:在內(nèi)存池上的分配策略是: 最小適配原則:按從小到大的順序,遍歷所有的內(nèi)存池,直到找到一個(gè)內(nèi)存池,其大最小適配原則:按從小到大的順序,遍歷所有的內(nèi)存池,直到找到一個(gè)內(nèi)存池,其大 小大于欲分配內(nèi)存的大小,就在該內(nèi)存池分配內(nèi)存。如果該內(nèi)存池已被用盡,則繼續(xù)小大于欲分配內(nèi)存的大小,就在該內(nèi)存池分配內(nèi)存。如果該內(nèi)存池已被用盡,則繼續(xù) 向下遍歷,找到下一個(gè)適合的內(nèi)存池。如果全部遍歷完都沒(méi)有找到可用的內(nèi)存池,則向下遍歷,找到下一個(gè)適合的內(nèi)存池。如果全部遍歷完都沒(méi)有找到可用的內(nèi)存池,則 改為在改為在heap上分配內(nèi)存。上分配內(nèi)存。 上面的策略對(duì)于上層的申請(qǐng)者是透明的,申請(qǐng)者只要傳入欲分配的內(nèi)存大小

29、即可,無(wú)上面的策略對(duì)于上層的申請(qǐng)者是透明的,申請(qǐng)者只要傳入欲分配的內(nèi)存大小即可,無(wú) 須關(guān)心內(nèi)存究竟是在哪里分配的。須關(guān)心內(nèi)存究竟是在哪里分配的。 保密信息 . 312021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 系統(tǒng)系統(tǒng)assert之后,選擇菜單之后,選擇菜單5,可以看到當(dāng)前所有,可以看到當(dāng)前所有pool的信息,類(lèi)似的信息,類(lèi)似 這樣:這樣: 保密信息 . 322021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 u3.內(nèi)存內(nèi)存Debug信息:信息: 為了方便在出現(xiàn)內(nèi)存問(wèn)題的時(shí)候調(diào)試,通常在分配內(nèi)存的時(shí)候?yàn)榱朔奖阍诔霈F(xiàn)內(nèi)存問(wèn)題的時(shí)候調(diào)試,通常在分配內(nèi)存的時(shí)候(heap和和pool),會(huì)額外,會(huì)額外

30、的多分配一個(gè)的多分配一個(gè)header,放在每一塊分配內(nèi)存的開(kāi)始。,放在每一塊分配內(nèi)存的開(kāi)始。header的結(jié)構(gòu)定義如下:的結(jié)構(gòu)定義如下: 結(jié)構(gòu)成員的意義如下:結(jié)構(gòu)成員的意義如下: pre , succ : 兩個(gè)指向兩個(gè)指向header結(jié)構(gòu)的指針,目的是將所有的結(jié)構(gòu)的指針,目的是將所有的header串成一張雙向鏈表。串成一張雙向鏈表。 , line: 分配該塊內(nèi)存的文件名和行號(hào)分配該塊內(nèi)存的文件名和行號(hào) size : 內(nèi)存大小內(nèi)存大小(不包括不包括header) block_num: 系統(tǒng)分配的內(nèi)存塊總計(jì)系統(tǒng)分配的內(nèi)存塊總計(jì) 此外,為了能檢查內(nèi)存越界,在每一塊分配內(nèi)存的最后也會(huì)額外多分配一個(gè)字節(jié)

31、做為此外,為了能檢查內(nèi)存越界,在每一塊分配內(nèi)存的最后也會(huì)額外多分配一個(gè)字節(jié)做為 END FLAG,內(nèi)存分配時(shí)該字節(jié)會(huì)被寫(xiě)入,內(nèi)存分配時(shí)該字節(jié)會(huì)被寫(xiě)入0 xAA。當(dāng)該內(nèi)存被釋放時(shí),會(huì)檢查該標(biāo)志。當(dāng)該內(nèi)存被釋放時(shí),會(huì)檢查該標(biāo)志 位,如果不為位,如果不為0 xAA,則說(shuō)明出現(xiàn)異常,系統(tǒng),則說(shuō)明出現(xiàn)異常,系統(tǒng)ASSERT。 保密信息 . 332021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 加入加入debug信息后的內(nèi)存如下:信息后的內(nèi)存如下: 保密信息 . 342021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 因?yàn)橛蓄~外加了這些因?yàn)橛蓄~外加了這些debug信息,所以如果我們要分配信息,所以如果我們要分配

32、N個(gè)字節(jié)的內(nèi)個(gè)字節(jié)的內(nèi) 存,那么實(shí)際上分配的大小是存,那么實(shí)際上分配的大小是:N + sizeof(MEM_HEADER_T) + 1.再再 考慮到字節(jié)對(duì)齊的需要,實(shí)際的空間比上面的數(shù)字可能還要大一點(diǎn)??紤]到字節(jié)對(duì)齊的需要,實(shí)際的空間比上面的數(shù)字可能還要大一點(diǎn)。 比如比如16字節(jié)的內(nèi)存池,其中每個(gè)內(nèi)存塊的大小其實(shí)是:字節(jié)的內(nèi)存池,其中每個(gè)內(nèi)存塊的大小其實(shí)是:16 + 24 + 4 (本應(yīng)是加本應(yīng)是加1,加,加4是為了字節(jié)對(duì)齊是為了字節(jié)對(duì)齊) Header里的里的pre指向前一塊分配的內(nèi)存,指向前一塊分配的內(nèi)存,next指向后一塊分配的內(nèi)指向后一塊分配的內(nèi) 存,所有分配的內(nèi)存,都通過(guò)存,所有分配

33、的內(nèi)存,都通過(guò)header里的里的pre和和succ指針串起來(lái),指針串起來(lái), 構(gòu)成一張雙向鏈表。每分配一塊新的內(nèi)存,就將這塊內(nèi)存的構(gòu)成一張雙向鏈表。每分配一塊新的內(nèi)存,就將這塊內(nèi)存的header 加到鏈表的最后。通過(guò)遍歷加到鏈表的最后。通過(guò)遍歷header構(gòu)成的鏈表,我們可以得到當(dāng)前構(gòu)成的鏈表,我們可以得到當(dāng)前 所有分配的內(nèi)存塊的信息。所有分配的內(nèi)存塊的信息。 保密信息 . 352021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 系統(tǒng)系統(tǒng)assert之后,選擇菜單之后,選擇菜單4,就可以打印出這些信息,類(lèi)似這樣,就可以打印出這些信息,類(lèi)似這樣: 保密信息 . 362021-7-12 MOCOR內(nèi)存

34、管理內(nèi)存管理 思考:思考: 應(yīng)用里分配一塊大小為應(yīng)用里分配一塊大小為N字節(jié)的內(nèi)存,實(shí)際在內(nèi)存里占了多少空間?字節(jié)的內(nèi)存,實(shí)際在內(nèi)存里占了多少空間? 保密信息 . 372021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 練習(xí):練習(xí): 前面我們已經(jīng)講了前面我們已經(jīng)講了MOCOR平臺(tái)各類(lèi)內(nèi)存的分配情況,下面需要你親平臺(tái)各類(lèi)內(nèi)存的分配情況,下面需要你親 自動(dòng)手加深理解。使用我們的樣機(jī),連上自動(dòng)手加深理解。使用我們的樣機(jī),連上log,主動(dòng),主動(dòng)assert,輸入,輸入 3,dump出當(dāng)前的內(nèi)存。輸入出當(dāng)前的內(nèi)存。輸入5,打出當(dāng)前的內(nèi)存信息。然后打開(kāi)內(nèi),打出當(dāng)前的內(nèi)存信息。然后打開(kāi)內(nèi) 存存dump文件,找到文

35、件,找到app heap的起始地址,從起始地址開(kāi)始,推出的起始地址,從起始地址開(kāi)始,推出 整個(gè)整個(gè)app heap的所有內(nèi)存塊的信息,然后用剛才打印出的信息驗(yàn)證的所有內(nèi)存塊的信息,然后用剛才打印出的信息驗(yàn)證 一下你的推導(dǎo)是否正確。一下你的推導(dǎo)是否正確。 保密信息 . 382021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 u4.物理內(nèi)存:物理內(nèi)存: 內(nèi)存管理的最終的對(duì)象就是物理內(nèi)存,但是,物理內(nèi)存并不能全部?jī)?nèi)存管理的最終的對(duì)象就是物理內(nèi)存,但是,物理內(nèi)存并不能全部 用于動(dòng)態(tài)分配,因?yàn)橐恍┤肿兞浚a等需要占用物理內(nèi)存,這用于動(dòng)態(tài)分配,因?yàn)橐恍┤肿兞?,代碼等需要占用物理內(nèi)存,這 些相當(dāng)于靜態(tài)分配

36、。而我們通常說(shuō)的內(nèi)存管理是指動(dòng)態(tài)的對(duì)內(nèi)存進(jìn)些相當(dāng)于靜態(tài)分配。而我們通常說(shuō)的內(nèi)存管理是指動(dòng)態(tài)的對(duì)內(nèi)存進(jìn) 行分配和釋放。那么哪些物理內(nèi)存是我們能夠動(dòng)態(tài)分配使用的呢,行分配和釋放。那么哪些物理內(nèi)存是我們能夠動(dòng)態(tài)分配使用的呢, 我們是如何知道可以動(dòng)態(tài)分配的物理內(nèi)存的地址范圍呢?我們是如何知道可以動(dòng)態(tài)分配的物理內(nèi)存的地址范圍呢? 以以6600L芯片為例,芯片為例,L所用的所用的NORMCP中的中的SRAM通常是通常是4M,這,這4M 就是我們所能夠用到的所有物理內(nèi)存。就是我們所能夠用到的所有物理內(nèi)存。OS啟動(dòng)后,會(huì)把物理內(nèi)存啟動(dòng)后,會(huì)把物理內(nèi)存 SRAM的地址映射到的地址映射到0 x04000000到到

37、0 x04400000這個(gè)區(qū)域。這個(gè)區(qū)域。 保密信息 . 392021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 Heap和和pool對(duì)應(yīng)的物理內(nèi)存的位置和大?。簩?duì)應(yīng)的物理內(nèi)存的位置和大?。?uint32 pool_1_addrPOOL_XX_SIZE(POOL_1_BLOCK_SIZE, POOL_1_BLOCK_NUM); uint32 pool_2_addrPOOL_XX_SIZE(POOL_2_BLOCK_SIZE, POOL_2_BLOCK_NUM); uint32 pool_3_addrPOOL_XX_SIZE(POOL_3_BLOCK_SIZE, POOL_3_BLOCK_NUM);

38、 uint32 pool_B_addrPOOL_XX_SIZE(POOL_B_BLOCK_SIZE, POOL_B_BLOCK_NUM); uint32 pool_C_addrPOOL_XX_SIZE(POOL_C_BLOCK_SIZE, POOL_C_BLOCK_NUM); uint32 BYTE_HEAP_ADDR byte_head_size 2 ; 保密信息 . 402021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 u5.內(nèi)存委托管理:內(nèi)存委托管理: 委托內(nèi)存管理實(shí)質(zhì)就是給了模塊創(chuàng)建自己的委托內(nèi)存管理實(shí)質(zhì)就是給了模塊創(chuàng)建自己的heap和和pool的機(jī)會(huì)。通的機(jī)會(huì)。通 常情況下我們使用的常

39、情況下我們使用的heap和和pool都是系統(tǒng)創(chuàng)建的。但有些模塊也想都是系統(tǒng)創(chuàng)建的。但有些模塊也想 先從系統(tǒng)的先從系統(tǒng)的heap里分出一塊大內(nèi)存,然后在這塊大內(nèi)存上,再根據(jù)里分出一塊大內(nèi)存,然后在這塊大內(nèi)存上,再根據(jù) 自己的需要細(xì)分出一些內(nèi)存塊來(lái)供本模塊使用。在沒(méi)有委托內(nèi)存管自己的需要細(xì)分出一些內(nèi)存塊來(lái)供本模塊使用。在沒(méi)有委托內(nèi)存管 理之前,這種細(xì)分的工作實(shí)際由各模塊自己來(lái)完成,實(shí)現(xiàn)的手法也理之前,這種細(xì)分的工作實(shí)際由各模塊自己來(lái)完成,實(shí)現(xiàn)的手法也 五花八門(mén)。有了委托內(nèi)存管理,模塊可以在分配的大內(nèi)存的基礎(chǔ)上,五花八門(mén)。有了委托內(nèi)存管理,模塊可以在分配的大內(nèi)存的基礎(chǔ)上, 再創(chuàng)建自己的再創(chuàng)建自己的h

40、eap和和pool,這些,這些heap和和pool的實(shí)現(xiàn)機(jī)制,同我們之的實(shí)現(xiàn)機(jī)制,同我們之 前講的系統(tǒng)的機(jī)制是基本一樣的。前講的系統(tǒng)的機(jī)制是基本一樣的。 保密信息 . 412021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 u6.BLOCK MEM: 關(guān)于關(guān)于BLOCK MEM可以參考可以參考MOOCR應(yīng)用模塊內(nèi)存使用接口應(yīng)用模塊內(nèi)存使用接口的的 第二章,如果還不清楚第二章,如果還不清楚block mem的目的和用法的,請(qǐng)務(wù)必先學(xué)習(xí)的目的和用法的,請(qǐng)務(wù)必先學(xué)習(xí) 上面這篇文檔。上面這篇文檔。 保密信息 . 422021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 幾個(gè)容易混淆的地方:幾個(gè)容易混淆的地方:

41、1. BLOCK MEM并不是在內(nèi)存中實(shí)際分配出一塊區(qū)域來(lái)進(jìn)行管理并不是在內(nèi)存中實(shí)際分配出一塊區(qū)域來(lái)進(jìn)行管理 (雖然舊的(雖然舊的MOCOR版本上確實(shí)是這樣的),版本上確實(shí)是這樣的),BLOCK MEM的分配的分配 依然是在依然是在app heap上完成的。既然是在上完成的。既然是在app heap上分配的,那么上分配的,那么 assert之后按之后按5,從,從app heap的信息里是可以找到當(dāng)前分配的的信息里是可以找到當(dāng)前分配的block mem的,比如這樣:的,比如這樣: 保密信息 . 432021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 保密信息 . 442021-7-12 MOCOR內(nèi)

42、存管理內(nèi)存管理 2.BLOCK MEM的管理機(jī)制中,為各塊的管理機(jī)制中,為各塊mem都定義了一個(gè)都定義了一個(gè)offset, 但這個(gè)但這個(gè)offset純粹是一個(gè)邏輯概念,它的作用是在分配純粹是一個(gè)邏輯概念,它的作用是在分配block mem 時(shí)判斷是否存在時(shí)判斷是否存在mem沖突。一個(gè)沖突。一個(gè)block在內(nèi)存中的實(shí)際位置同這個(gè)在內(nèi)存中的實(shí)際位置同這個(gè) offset沒(méi)有任何關(guān)系。沒(méi)有任何關(guān)系。 保密信息 . 452021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) ThreadX的內(nèi)存管理的內(nèi)存管理 MOCOR的內(nèi)存管理的內(nèi)存管理 MOCOR內(nèi)存內(nèi)存bu

43、g實(shí)例分析實(shí)例分析 保密信息 . 462021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 內(nèi)存不足內(nèi)存不足: 內(nèi)存不足是經(jīng)常遇到的問(wèn)題,內(nèi)存不足根據(jù)產(chǎn)生的原內(nèi)存不足是經(jīng)常遇到的問(wèn)題,內(nèi)存不足根據(jù)產(chǎn)生的原 因,還可以分為內(nèi)存泄露引起的不足,內(nèi)存碎片引起的因,還可以分為內(nèi)存泄露引起的不足,內(nèi)存碎片引起的 不足,以及真正的內(nèi)存不足。下面我們以幾個(gè)具體的例不足,以及真正的內(nèi)存不足。下面我們以幾個(gè)具體的例 子來(lái)分析。子來(lái)分析。 保密信息 . 472021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 u1.內(nèi)存泄漏:內(nèi)存泄漏: 內(nèi)存泄露是指分配了一塊內(nèi)存在使用完后卻沒(méi)有釋放,造成系統(tǒng)中內(nèi)

44、存泄露是指分配了一塊內(nèi)存在使用完后卻沒(méi)有釋放,造成系統(tǒng)中 可用內(nèi)存越來(lái)越少,最后死機(jī)。內(nèi)存泄露引起的死機(jī)很容易定位,可用內(nèi)存越來(lái)越少,最后死機(jī)。內(nèi)存泄露引起的死機(jī)很容易定位, 只要在死機(jī)后輸入只要在死機(jī)后輸入4,打出當(dāng)前所有分配的內(nèi)存信息,查看是否有大,打出當(dāng)前所有分配的內(nèi)存信息,查看是否有大 量的重復(fù)的內(nèi)存分配就可以知道。量的重復(fù)的內(nèi)存分配就可以知道。 實(shí)例:某客戶(hù)項(xiàng)目,測(cè)試中反復(fù)撥號(hào)出現(xiàn)死機(jī),死機(jī)信息為:實(shí)例:某客戶(hù)項(xiàng)目,測(cè)試中反復(fù)撥號(hào)出現(xiàn)死機(jī),死機(jī)信息為: File: RTOSsourcesrccthreadx_mem.c Line: 494 ASSERT(ASSERT: Error 0

45、 x10 (No memory, unable to allocate !), mmipb_wintab.c, line=11550, param=0 x4650) 打出當(dāng)前所有分配的信息,發(fā)現(xiàn)異常打出當(dāng)前所有分配的信息,發(fā)現(xiàn)異常,有一條分配信息出現(xiàn)多次:有一條分配信息出現(xiàn)多次: 保密信息 . 482021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 保密信息 . 492021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 u2.內(nèi)存碎片:內(nèi)存碎片: 如果系統(tǒng)中存在內(nèi)存碎片,可能會(huì)出現(xiàn)雖然剩余的總內(nèi)存數(shù)是足夠如果系統(tǒng)中存在內(nèi)存碎片,可能會(huì)出現(xiàn)雖然剩余的總內(nèi)存數(shù)是足夠 的,但依然分

46、配不出內(nèi)存的情況。的,但依然分配不出內(nèi)存的情況。 實(shí)例,某客戶(hù)項(xiàng)目,后臺(tái)運(yùn)行實(shí)例,某客戶(hù)項(xiàng)目,后臺(tái)運(yùn)行QQ,進(jìn)入,進(jìn)入DC后死機(jī)。后死機(jī)。 File: RTOSsourcesrccthreadx_mem.c Line: 494 ASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), block_mem.c, line=563, param=0 x113004) 從死機(jī)信息可以看出,要分配的內(nèi)存大小為從死機(jī)信息可以看出,要分配的內(nèi)存大小為0 x113004(1126404),這么大的內(nèi)存只可),這么大的內(nèi)存只可 能從能從heap

47、上分配,查看上分配,查看app heap的信息如下:的信息如下: 保密信息 . 502021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 保密信息 . 512021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 我們重點(diǎn)關(guān)注畫(huà)紅圈的三塊內(nèi)存,可以看到,剩余的總內(nèi)存我們重點(diǎn)關(guān)注畫(huà)紅圈的三塊內(nèi)存,可以看到,剩余的總內(nèi)存1495344,大于欲分配的內(nèi)存,但是,大于欲分配的內(nèi)存,但是 編號(hào)編號(hào)1和和3的兩塊空閑內(nèi)存正好被編號(hào)的兩塊空閑內(nèi)存正好被編號(hào)2的內(nèi)存隔開(kāi)了,的內(nèi)存隔開(kāi)了,1,和和3的大小都不超過(guò)的大小都不超過(guò)1126404,所以無(wú)法,所以無(wú)法 分配,這就是一個(gè)典型的內(nèi)存碎片造成內(nèi)存

48、不足的場(chǎng)景。要解決這個(gè)問(wèn)題,我們就要想辦法把兩分配,這就是一個(gè)典型的內(nèi)存碎片造成內(nèi)存不足的場(chǎng)景。要解決這個(gè)問(wèn)題,我們就要想辦法把兩 塊空閑內(nèi)存連在一起,主要就是要調(diào)整這幾塊內(nèi)存的分配和釋放的順序。我們不妨用逆向思維來(lái)塊空閑內(nèi)存連在一起,主要就是要調(diào)整這幾塊內(nèi)存的分配和釋放的順序。我們不妨用逆向思維來(lái) 分析,先看一下造成內(nèi)存碎片的順序是怎樣的,然后我們只要避免這種順序就可以了。首先在最分析,先看一下造成內(nèi)存碎片的順序是怎樣的,然后我們只要避免這種順序就可以了。首先在最 初時(shí),初時(shí),1,2,3這三塊內(nèi)存實(shí)際是一整塊空閑內(nèi)存。前面我們提過(guò),字節(jié)池分配內(nèi)存時(shí)有一個(gè)反向分這三塊內(nèi)存實(shí)際是一整塊空閑內(nèi)存。

49、前面我們提過(guò),字節(jié)池分配內(nèi)存時(shí)有一個(gè)反向分 配的概念,當(dāng)要分配的的內(nèi)存大于配的概念,當(dāng)要分配的的內(nèi)存大于80K時(shí),是從底向上分配的。所以分配和釋放的順序是:時(shí),是從底向上分配的。所以分配和釋放的順序是: 第一步:分配內(nèi)存第一步:分配內(nèi)存3; 第二步:分配內(nèi)存第二步:分配內(nèi)存2; 第三步:釋放內(nèi)存第三步:釋放內(nèi)存3 由此可以自然的想到解決的辦法,就是調(diào)整上面的由此可以自然的想到解決的辦法,就是調(diào)整上面的3個(gè)步驟,具體可以有兩種辦法:個(gè)步驟,具體可以有兩種辦法: 內(nèi)存塊內(nèi)存塊2先于先于3分配,這樣分配,這樣3釋放后自然同釋放后自然同1連在一起。連在一起。 內(nèi)存塊內(nèi)存塊2在在3釋放之后再分配,這樣釋

50、放之后再分配,這樣2占了內(nèi)存占了內(nèi)存3的位置,剩余的內(nèi)存也是連續(xù)的。的位置,剩余的內(nèi)存也是連續(xù)的。 具體用什么方法,就要根據(jù)實(shí)際的具體情況,看哪一種方法是最可行的。在客戶(hù)的這個(gè)問(wèn)題中,具體用什么方法,就要根據(jù)實(shí)際的具體情況,看哪一種方法是最可行的。在客戶(hù)的這個(gè)問(wèn)題中, 內(nèi)存塊內(nèi)存塊3是一個(gè)第三方桌面插件分配的,內(nèi)存塊是一個(gè)第三方桌面插件分配的,內(nèi)存塊2是是QQ分配的。所以第分配的。所以第2種方法最可行,在分配種方法最可行,在分配 QQ的內(nèi)存前,先釋放掉第三方桌面插件的內(nèi)存,問(wèn)題由此解決。的內(nèi)存前,先釋放掉第三方桌面插件的內(nèi)存,問(wèn)題由此解決。 保密信息 . 522021-7-12 MOCOR內(nèi)存

51、內(nèi)存bug實(shí)例分析實(shí)例分析 注意:注意: 并不是所有的內(nèi)存碎片問(wèn)題都能夠通過(guò)這樣的調(diào)整來(lái)得到解決。并不是所有的內(nèi)存碎片問(wèn)題都能夠通過(guò)這樣的調(diào)整來(lái)得到解決。 系統(tǒng)運(yùn)行的過(guò)程中,一些內(nèi)存碎片的產(chǎn)生是無(wú)法避免的,這種情況系統(tǒng)運(yùn)行的過(guò)程中,一些內(nèi)存碎片的產(chǎn)生是無(wú)法避免的,這種情況 下內(nèi)存碎片無(wú)法得到消除或消除的難度很大。下內(nèi)存碎片無(wú)法得到消除或消除的難度很大。 保密信息 . 532021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 u3.實(shí)際內(nèi)存不足:實(shí)際內(nèi)存不足: 如果出現(xiàn)剩余的內(nèi)存不夠分配,此時(shí)查看內(nèi)存分配的情如果出現(xiàn)剩余的內(nèi)存不夠分配,此時(shí)查看內(nèi)存分配的情 況也沒(méi)有異常(也就是說(shuō)已經(jīng)排除

52、了內(nèi)存泄露和碎片的況也沒(méi)有異常(也就是說(shuō)已經(jīng)排除了內(nèi)存泄露和碎片的 原因),這種情況就是真正的內(nèi)存不足了。遇到這種情原因),這種情況就是真正的內(nèi)存不足了。遇到這種情 況,一般有這些思路:況,一般有這些思路: 要求客戶(hù)裁剪功能,減少內(nèi)存的使用,通??蛻?hù)會(huì)對(duì)平要求客戶(hù)裁剪功能,減少內(nèi)存的使用,通??蛻?hù)會(huì)對(duì)平 臺(tái)版本進(jìn)行一些定制,比如增加一些第三方應(yīng)用等等,臺(tái)版本進(jìn)行一些定制,比如增加一些第三方應(yīng)用等等, 這些新增的模塊往往會(huì)造成內(nèi)存使用的增加。這些新增的模塊往往會(huì)造成內(nèi)存使用的增加。 如果某些操作很耗內(nèi)存,那么執(zhí)行這些操作時(shí)最好將其如果某些操作很耗內(nèi)存,那么執(zhí)行這些操作時(shí)最好將其 他操作退出,盡量

53、避免并發(fā)。他操作退出,盡量避免并發(fā)。 以上都不行的話(huà)最后只能通過(guò)增大以上都不行的話(huà)最后只能通過(guò)增大heap size來(lái)解決。來(lái)解決。 保密信息 . 542021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 某客戶(hù)上報(bào)問(wèn)題,進(jìn)文件管理器,選擇一張某客戶(hù)上報(bào)問(wèn)題,進(jìn)文件管理器,選擇一張gif圖片發(fā)彩信圖片發(fā)彩信 時(shí)出現(xiàn)內(nèi)存不足死機(jī):時(shí)出現(xiàn)內(nèi)存不足死機(jī): File: RTOSsourcesrccthreadx_mem.c Line: 494 ASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), block_mem.c, l

54、ine=521, param=0 x25804) 從上面的信息可以看到欲分配的內(nèi)存大小是從上面的信息可以看到欲分配的內(nèi)存大小是 0 x25804(153604)。 查看查看app heap的使用情況如下的使用情況如下 保密信息 . 552021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 保密信息 . 562021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 可以看到當(dāng)前剩余的總內(nèi)存也不過(guò)是可以看到當(dāng)前剩余的總內(nèi)存也不過(guò)是141744,其中最大一塊空閑內(nèi)存是,其中最大一塊空閑內(nèi)存是 0 x1aa4c(109132),還差,還差0 x25804-0 x1aa4c = 0 xADB

55、8(44472)才夠分配。)才夠分配。 我們用剛才的幾種思路分析一下:我們用剛才的幾種思路分析一下: 裁剪功能,因?yàn)闆](méi)有第三方的東西,這個(gè)不考慮裁剪功能,因?yàn)闆](méi)有第三方的東西,這個(gè)不考慮 避免并發(fā)。通過(guò)分析內(nèi)存,可以看到分配的內(nèi)存實(shí)際上可以分為兩大塊(見(jiàn)上圖),避免并發(fā)。通過(guò)分析內(nèi)存,可以看到分配的內(nèi)存實(shí)際上可以分為兩大塊(見(jiàn)上圖), 一塊是上面紅框的部分,主要是由一塊是上面紅框的部分,主要是由FMM分配的。另一塊是下面紅框部分,主要是由分配的。另一塊是下面紅框部分,主要是由 MMS分配,所以這里存在分配,所以這里存在MMS和和FMM并發(fā)的情況。如果我們?cè)诎l(fā)送彩信之前就先退并發(fā)的情況。如果我們

56、在發(fā)送彩信之前就先退 出出FMM的話(huà),可以解決此問(wèn)題。的話(huà),可以解決此問(wèn)題。 增大增大heap。前面我們已經(jīng)算出當(dāng)前差了。前面我們已經(jīng)算出當(dāng)前差了44472字節(jié),修改字節(jié),修改mem_cfg.c,將,將app heap 的大小增加至少的大小增加至少44K。需要注意的是,如果要增大。需要注意的是,如果要增大heap,首先要確認(rèn)一下當(dāng)然,首先要確認(rèn)一下當(dāng)然ram是是 否還有這么多可用的空間,可以通過(guò)查看否還有這么多可用的空間,可以通過(guò)查看map文件最后的幾行信息:文件最后的幾行信息: Total RO Size(Code + RO Data) 7530419 (7353.92kB) Total R

57、W Size(RW Data + ZI Data) 3944375 (3851.93kB) Total ROM Size(Code + RO Data + RW Data) 7586078 (7408.28kB) 紅色的紅色的RW size就是我們要關(guān)注的,可以看到當(dāng)前就是我們要關(guān)注的,可以看到當(dāng)前RW使用了使用了3851K,而,而RAM的總數(shù)的總數(shù) 是是4096K,所以還有充足的空間,所以還有充足的空間,heap增加個(gè)幾十增加個(gè)幾十K沒(méi)有什么問(wèn)題。沒(méi)有什么問(wèn)題。 可以看到使用可以看到使用2和和3都可以解決問(wèn)題,通常把增大都可以解決問(wèn)題,通常把增大heap作為最后的手段。作為最后的手段。 保密

58、信息 . 572021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 內(nèi)存覆蓋:內(nèi)存覆蓋: 內(nèi)存覆蓋也是常見(jiàn)的一類(lèi)內(nèi)存問(wèn)題,引起內(nèi)存覆蓋內(nèi)存覆蓋也是常見(jiàn)的一類(lèi)內(nèi)存問(wèn)題,引起內(nèi)存覆蓋 的原因很多,往往沒(méi)有固定規(guī)律可循。而且有時(shí)出現(xiàn)覆的原因很多,往往沒(méi)有固定規(guī)律可循。而且有時(shí)出現(xiàn)覆 蓋后并不立刻死機(jī),這樣無(wú)法確認(rèn)第一現(xiàn)場(chǎng),增大了解蓋后并不立刻死機(jī),這樣無(wú)法確認(rèn)第一現(xiàn)場(chǎng),增大了解 決問(wèn)題的難度。但在決問(wèn)題的難度。但在MOCOR平臺(tái)下,我們有一個(gè)非常有平臺(tái)下,我們有一個(gè)非常有 用的工具:用的工具:Bus Monitor。利用。利用Bus Monitor(后文簡(jiǎn)稱(chēng)(后文簡(jiǎn)稱(chēng) BM),我們有一個(gè)解決

59、覆蓋問(wèn)題的一般性思路:首先確),我們有一個(gè)解決覆蓋問(wèn)題的一般性思路:首先確 定被覆蓋內(nèi)存的地址定被覆蓋內(nèi)存的地址(可能是一個(gè)地址范圍可能是一個(gè)地址范圍),如果問(wèn)題可,如果問(wèn)題可 以重現(xiàn),且每次被覆蓋的地址比較固定,則可以用以重現(xiàn),且每次被覆蓋的地址比較固定,則可以用BM監(jiān)監(jiān) 控被覆蓋的地址,這樣當(dāng)內(nèi)存被覆蓋時(shí)會(huì)第一時(shí)間死機(jī),控被覆蓋的地址,這樣當(dāng)內(nèi)存被覆蓋時(shí)會(huì)第一時(shí)間死機(jī), 可以迅速定位??梢匝杆俣ㄎ弧us Monitor的用法比較簡(jiǎn)單,可以參考的用法比較簡(jiǎn)單,可以參考 相關(guān)文檔。相關(guān)文檔。 保密信息 . 582021-7-12 MOCOR內(nèi)存內(nèi)存bug實(shí)例分析實(shí)例分析 u1.案例一案例一

60、內(nèi)存寫(xiě)入時(shí)越界是出現(xiàn)內(nèi)存覆蓋的一個(gè)常見(jiàn)原因,相對(duì)來(lái)說(shuō)也比內(nèi)存寫(xiě)入時(shí)越界是出現(xiàn)內(nèi)存覆蓋的一個(gè)常見(jiàn)原因,相對(duì)來(lái)說(shuō)也比 較好查的,只要找到越界的那塊內(nèi)存基本就可以定位,我們看下面較好查的,只要找到越界的那塊內(nèi)存基本就可以定位,我們看下面 的例子:的例子: 客戶(hù)項(xiàng)目發(fā)現(xiàn)進(jìn)入電話(huà)本偶而會(huì)出現(xiàn)死機(jī),死機(jī)現(xiàn)場(chǎng):客戶(hù)項(xiàng)目發(fā)現(xiàn)進(jìn)入電話(huà)本偶而會(huì)出現(xiàn)死機(jī),死機(jī)現(xiàn)場(chǎng): File: RTOSsourcesrccthreadx_mem.c Line: 364 ASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), wdp_customer.c, line

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論