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

下載本文檔

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

文檔簡介

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

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

3、個大致的調(diào)用層次如下圖所示:內(nèi)存管理體系的一個大致的調(diào)用層次如下圖所示: 保密信息 . 52021-7-12 MOCOR內(nèi)存管理的基本架構(gòu)內(nèi)存管理的基本架構(gòu) 從可用的內(nèi)存資源的角度,還可以得到下面的一個內(nèi)存分配圖。從可用的內(nèi)存資源的角度,還可以得到下面的一個內(nèi)存分配圖。 保密信息 . 62021-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)存bug實例分析實例分析 保密信息 . 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é)池是一個連續(xù)的內(nèi)存塊。在字節(jié)池中,內(nèi)存的分配以字節(jié)為單位,任意大小內(nèi)存字節(jié)池是一個連續(xù)的內(nèi)存塊。在字節(jié)池中,內(nèi)存的分配以字節(jié)為單位,任意大小 的內(nèi)存都可以在字節(jié)池上分配(受限于內(nèi)存的容量)。的內(nèi)存都可以在字節(jié)池上分配(受限于內(nèi)存的容量)。 內(nèi)存字節(jié)池類似于內(nèi)存字節(jié)池類似于C語言里

5、的堆語言里的堆(heap),所以,字節(jié)池我們也可以把它叫做字節(jié)堆,所以,字節(jié)池我們也可以把它叫做字節(jié)堆, 代碼里我們也可以看到創(chuàng)建的字節(jié)池通常以代碼里我們也可以看到創(chuàng)建的字節(jié)池通常以heap來命名。但與一般意義上的堆的不來命名。但與一般意義上的堆的不 同在于,同在于,ThreadX里的字節(jié)池可以有多個,里的字節(jié)池可以有多個,MOCOR平臺也是利用了這一特性,根據(jù)平臺也是利用了這一特性,根據(jù) 不同的需求而創(chuàng)建了多個不同的需求而創(chuàng)建了多個heap。 每一個字節(jié)池都有一個相應(yīng)的字節(jié)池控制塊,通常是一個全局結(jié)構(gòu)??刂茐K包括對內(nèi)每一個字節(jié)池都有一個相應(yīng)的字節(jié)池控制塊,通常是一個全局結(jié)構(gòu)??刂茐K包括對內(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)存類似于從字節(jié)池中分配內(nèi)存類似于C語言的語言的malloc調(diào)用,該調(diào)用返回所需內(nèi)存的數(shù)量(以字調(diào)用,該調(diào)用返回所需內(nèi)存的數(shù)量(以字 節(jié)為單位)。分配的原則是節(jié)為單位)。分配的原則是“首次符合首次符合”原則,就是說,當?shù)谝粋€

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

8、一個具體數(shù)值,在分配內(nèi)存時,如果要分配的內(nèi)存大小大于這 一數(shù)值,則從字節(jié)池的底部開始分配。采用這種分配方式是為了減少內(nèi)存碎片的產(chǎn)生,一數(shù)值,則從字節(jié)池的底部開始分配。采用這種分配方式是為了減少內(nèi)存碎片的產(chǎn)生, 盡量把大內(nèi)存的分配區(qū)域和小內(nèi)存的分配區(qū)域分開。目前系統(tǒng)里定義的盡量把大內(nèi)存的分配區(qū)域和小內(nèi)存的分配區(qū)域分開。目前系統(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)存布局: 以一個分配了兩次的字節(jié)池為例,在內(nèi)存中的情況如下:以一個分配了兩次的字節(jié)池為例,在內(nèi)存中

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

10、節(jié)的空閑塊,花多長時間找到這 塊內(nèi)存也是沒有保證的。因此,在時間要求苛刻的任務(wù)中應(yīng)避免使塊內(nèi)存也是沒有保證的。因此,在時間要求苛刻的任務(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)中有一個內(nèi)存字節(jié)池,并且已經(jīng)從中分配了幾次假定系統(tǒng)中有一個內(nèi)存字節(jié)池,并且已經(jīng)從中分配了幾次 內(nèi)存。當內(nèi)存池中還有內(nèi)存。當內(nèi)存池中還有500字節(jié)的剩余內(nèi)存時,應(yīng)用程序申字節(jié)的剩余內(nèi)存時,應(yīng)用程序申

11、 請請200字節(jié)的內(nèi)存,在什么情況下,這樣的申請不能滿足?字節(jié)的內(nèi)存,在什么情況下,這樣的申請不能滿足? 保密信息 . 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)存塊池也是一個連續(xù)的字節(jié)塊,但它是由一定數(shù)量的固定內(nèi)存塊池也是一個連續(xù)的字節(jié)塊,但它是由一定數(shù)量的固定szie的內(nèi)存塊組成的。因的內(nèi)存塊組成的。因 此,從一個內(nèi)存塊池中分配出的內(nèi)存總是固定大小的。此,從一個內(nèi)存塊池中分配出的內(nèi)存總是固定大小的。 相比字節(jié)

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

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

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)存塊組成一個內(nèi)存塊池中分配內(nèi)存是非??斓?,主要得益于內(nèi)存塊池中的所有空閑內(nèi)存塊組成一個 鏈表鏈表(即上面結(jié)構(gòu)中的即上面結(jié)構(gòu)中的tx_block_pool_available_list)。每次分配時只需要取鏈表頭即。每次分配時只需要取鏈表頭即 可,無須遍歷內(nèi)存塊池來找到空

15、閑塊???,無須遍歷內(nè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)存塊池 思考思考 如何計算一個內(nèi)存塊池所占用的物理內(nèi)存大小如何計算一個內(nèi)存塊池所占用的物理內(nèi)存大小? 保密信息 . 212021-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)存bug實例分析實例分析 保密信息 .

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

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

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

19、LOC_BASE, SCI_ALLOC_CONST SCI_ALLOC_APP。 保密信息 . 242021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 三個三個heap: Base heap: 主要給主要給PS,Layer1等使用。這個等使用。這個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、三個三個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)存分配信息, 類似這樣:類似這樣: 保密信息 . 272021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 思考:思考: 前面講了前面講了MOCOR里有三個不同用途的里有三個不同用途的heap,想一想哪些內(nèi)存是要在,想一想哪些內(nèi)存是要在 static heap里分配的,如果這些內(nèi)存改在里分配的,如果這些內(nèi)存改在app heap上會有什么問題?上會有什么問題? 嘗試舉出幾個實際的例子來說明。嘗試舉出幾個實際的例子來說明。 保密信息 . 282021-7-12 MOCOR內(nèi)存管理內(nèi)存管

22、理 u2.內(nèi)存池管理:內(nèi)存池管理: 這個所說的內(nèi)存池這個所說的內(nèi)存池(pool)就是特指前面提到的內(nèi)存塊池。之前我們提到過,為了避免浪費內(nèi)存,就是特指前面提到的內(nèi)存塊池。之前我們提到過,為了避免浪費內(nèi)存, 通常是分配多個內(nèi)存池,分別對應(yīng)不同的大小。通常是分配多個內(nèi)存池,分別對應(yīng)不同的大小。MOCOR平臺一共創(chuàng)建了平臺一共創(chuàng)建了12個內(nèi)存池,其對應(yīng)的個內(nèi)存池,其對應(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)常會有調(diào)整可能并不一致,經(jīng)常會有調(diào)整) 保密信息 . 292021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 什么時候在什么時候在heap上分配,什么時候在內(nèi)

27、存池上分配?上分配,什么時候在內(nèi)存池上分配? MOCOR對分配內(nèi)存的位置有如下的約定:只有分配的內(nèi)存的大小超對分配內(nèi)存的位置有如下的約定:只有分配的內(nèi)存的大小超 過過mem_cfg.c里定義的最大的內(nèi)存塊池的大小,內(nèi)存才會在里定義的最大的內(nèi)存塊池的大小,內(nèi)存才會在heap里里 分配,否則就在內(nèi)存塊池里分配。目前分配,否則就在內(nèi)存塊池里分配。目前MOCOR平臺定義的最大的內(nè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)存池,直到找到一個內(nèi)存池,其大最小適配原則:按從小到大的順序,遍歷所有的內(nèi)存池,直到找到一個內(nèi)存池,其大 小大于欲分配內(nèi)存的大小,就在該內(nèi)存池分配內(nèi)存。如果該內(nèi)存池已被用盡,則繼續(xù)小大于欲分配內(nèi)存的大小,就在該內(nèi)存池分配內(nèi)存。如果該內(nèi)存池已被用盡,則繼續(xù) 向下遍歷,找到下一個適合的內(nèi)存池。如果全部遍歷完都沒有找到可用的內(nèi)存池,則向下遍歷,找到下一個適合的內(nèi)存池。如果全部遍歷完都沒有找到可用的內(nèi)存池,則 改為在改為在heap上分配內(nèi)存。上分配內(nèi)存。 上面的策略對于上層的申請者是透明的,申請者只要傳入欲分配的內(nèi)存大小

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

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

31、做為此外,為了能檢查內(nèi)存越界,在每一塊分配內(nèi)存的最后也會額外多分配一個字節(jié)做為 END FLAG,內(nèi)存分配時該字節(jié)會被寫入,內(nèi)存分配時該字節(jié)會被寫入0 xAA。當該內(nèi)存被釋放時,會檢查該標志。當該內(nèi)存被釋放時,會檢查該標志 位,如果不為位,如果不為0 xAA,則說明出現(xiàn)異常,系統(tǒng),則說明出現(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)存管理 因為有額外加了這些因為有額外加了這些debug信息,所以如果我們要分配信息,所以如果我們要分配

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

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

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

35、件,找到app heap的起始地址,從起始地址開始,推出的起始地址,從起始地址開始,推出 整個整個app heap的所有內(nèi)存塊的信息,然后用剛才打印出的信息驗證的所有內(nèi)存塊的信息,然后用剛才打印出的信息驗證 一下你的推導(dǎo)是否正確。一下你的推導(dǎo)是否正確。 保密信息 . 382021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 u4.物理內(nèi)存:物理內(nèi)存: 內(nèi)存管理的最終的對象就是物理內(nèi)存,但是,物理內(nèi)存并不能全部內(nèi)存管理的最終的對象就是物理內(nèi)存,但是,物理內(nèi)存并不能全部 用于動態(tài)分配,因為一些全局變量,代碼等需要占用物理內(nèi)存,這用于動態(tài)分配,因為一些全局變量,代碼等需要占用物理內(nèi)存,這 些相當于靜態(tài)分配

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

37、0 x04400000這個區(qū)域。這個區(qū)域。 保密信息 . 392021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 Heap和和pool對應(yīng)的物理內(nèi)存的位置和大?。簩?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)存管理實質(zhì)就是給了模塊創(chuàng)建自己的委托內(nèi)存管理實質(zhì)就是給了模塊創(chuàng)建自己的heap和和pool的機會。通的機會。通 常情況下我們使用的常

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ù) 自己的需要細分出一些內(nèi)存塊來供本模塊使用。在沒有委托內(nèi)存管自己的需要細分出一些內(nèi)存塊來供本模塊使用。在沒有委托內(nèi)存管 理之前,這種細分的工作實際由各模塊自己來完成,實現(xiàn)的手法也理之前,這種細分的工作實際由各模塊自己來完成,實現(xiàn)的手法也 五花八門。有了委托內(nèi)存管理,模塊可以在分配的大內(nèi)存的基礎(chǔ)上,五花八門。有了委托內(nèi)存管理,模塊可以在分配的大內(nèi)存的基礎(chǔ)上, 再創(chuàng)建自己的再創(chuàng)建自己的h

40、eap和和pool,這些,這些heap和和pool的實現(xiàn)機制,同我們之的實現(xiàn)機制,同我們之 前講的系統(tǒng)的機制是基本一樣的。前講的系統(tǒng)的機制是基本一樣的。 保密信息 . 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的目的和用法的,請務(wù)必先學(xué)習(xí)的目的和用法的,請務(wù)必先學(xué)習(xí) 上面這篇文檔。上面這篇文檔。 保密信息 . 422021-7-12 MOCOR內(nèi)存管理內(nèi)存管理 幾個容易混淆的地方:幾個容易混淆的地方:

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

42、存管理內(nèi)存管理 2.BLOCK MEM的管理機制中,為各塊的管理機制中,為各塊mem都定義了一個都定義了一個offset, 但這個但這個offset純粹是一個邏輯概念,它的作用是在分配純粹是一個邏輯概念,它的作用是在分配block mem 時判斷是否存在時判斷是否存在mem沖突。一個沖突。一個block在內(nèi)存中的實際位置同這個在內(nèi)存中的實際位置同這個 offset沒有任何關(guān)系。沒有任何關(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實例分析實例分析 保密信息 . 462021-7-12 MOCOR內(nèi)存內(nèi)存bug實例分析實例分析 內(nèi)存不足內(nèi)存不足: 內(nèi)存不足是經(jīng)常遇到的問題,內(nèi)存不足根據(jù)產(chǎn)生的原內(nèi)存不足是經(jīng)常遇到的問題,內(nèi)存不足根據(jù)產(chǎn)生的原 因,還可以分為內(nèi)存泄露引起的不足,內(nèi)存碎片引起的因,還可以分為內(nèi)存泄露引起的不足,內(nèi)存碎片引起的 不足,以及真正的內(nèi)存不足。下面我們以幾個具體的例不足,以及真正的內(nèi)存不足。下面我們以幾個具體的例 子來分析。子來分析。 保密信息 . 472021-7-12 MOCOR內(nèi)存內(nèi)存bug實例分析實例分析 u1.內(nèi)存泄漏:內(nèi)存泄漏: 內(nèi)存泄露是指分配了一塊內(nèi)存在使用完后卻沒有釋放,造成系統(tǒng)中內(nèi)

44、存泄露是指分配了一塊內(nèi)存在使用完后卻沒有釋放,造成系統(tǒng)中 可用內(nèi)存越來越少,最后死機。內(nèi)存泄露引起的死機很容易定位,可用內(nèi)存越來越少,最后死機。內(nèi)存泄露引起的死機很容易定位, 只要在死機后輸入只要在死機后輸入4,打出當前所有分配的內(nèi)存信息,查看是否有大,打出當前所有分配的內(nèi)存信息,查看是否有大 量的重復(fù)的內(nèi)存分配就可以知道。量的重復(fù)的內(nèi)存分配就可以知道。 實例:某客戶項目,測試中反復(fù)撥號出現(xiàn)死機,死機信息為:實例:某客戶項目,測試中反復(fù)撥號出現(xiàn)死機,死機信息為: 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) 打出當前所有分配的信息,發(fā)現(xiàn)異常打出當前所有分配的信息,發(fā)現(xiàn)異常,有一條分配信息出現(xiàn)多次:有一條分配信息出現(xiàn)多次: 保密信息 . 482021-7-12 MOCOR內(nèi)存內(nèi)存bug實例分析實例分析 保密信息 . 492021-7-12 MOCOR內(nèi)存內(nèi)存bug實例分析實例分析 u2.內(nèi)存碎片:內(nèi)存碎片: 如果系統(tǒng)中存在內(nèi)存碎片,可能會出現(xiàn)雖然剩余的總內(nèi)存數(shù)是足夠如果系統(tǒng)中存在內(nèi)存碎片,可能會出現(xiàn)雖然剩余的總內(nèi)存數(shù)是足夠 的,但依然分

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

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

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

49、前面我們提過,字節(jié)池分配內(nèi)存時有一個反向分 配的概念,當要分配的的內(nèi)存大于配的概念,當要分配的的內(nèi)存大于80K時,是從底向上分配的。所以分配和釋放的順序是:時,是從底向上分配的。所以分配和釋放的順序是: 第一步:分配內(nèi)存第一步:分配內(nèi)存3; 第二步:分配內(nèi)存第二步:分配內(nèi)存2; 第三步:釋放內(nèi)存第三步:釋放內(nèi)存3 由此可以自然的想到解決的辦法,就是調(diào)整上面的由此可以自然的想到解決的辦法,就是調(diào)整上面的3個步驟,具體可以有兩種辦法:個步驟,具體可以有兩種辦法: 內(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ù)實際的具體情況,看哪一種方法是最可行的。在客戶的這個問題中,具體用什么方法,就要根據(jù)實際的具體情況,看哪一種方法是最可行的。在客戶的這個問題中, 內(nèi)存塊內(nèi)存塊3是一個第三方桌面插件分配的,內(nèi)存塊是一個第三方桌面插件分配的,內(nèi)存塊2是是QQ分配的。所以第分配的。所以第2種方法最可行,在分配種方法最可行,在分配 QQ的內(nèi)存前,先釋放掉第三方桌面插件的內(nèi)存,問題由此解決。的內(nèi)存前,先釋放掉第三方桌面插件的內(nèi)存,問題由此解決。 保密信息 . 522021-7-12 MOCOR內(nèi)存

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

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

53、避免并發(fā)。他操作退出,盡量避免并發(fā)。 以上都不行的話最后只能通過增大以上都不行的話最后只能通過增大heap size來解決。來解決。 保密信息 . 542021-7-12 MOCOR內(nèi)存內(nèi)存bug實例分析實例分析 某客戶上報問題,進文件管理器,選擇一張某客戶上報問題,進文件管理器,選擇一張gif圖片發(fā)彩信圖片發(fā)彩信 時出現(xiàn)內(nèi)存不足死機:時出現(xiàn)內(nèi)存不足死機: 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實例分析實例分析 保密信息 . 562021-7-12 MOCOR內(nèi)存內(nèi)存bug實例分析實例分析 可以看到當前剩余的總內(nèi)存也不過是可以看到當前剩余的總內(nèi)存也不過是141744,其中最大一塊空閑內(nèi)存是,其中最大一塊空閑內(nèi)存是 0 x1aa4c(109132),還差,還差0 x25804-0 x1aa4c = 0 xADB

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

56、在發(fā)送彩信之前就先退 出出FMM的話,可以解決此問題。的話,可以解決此問題。 增大增大heap。前面我們已經(jīng)算出當前差了。前面我們已經(jīng)算出當前差了44472字節(jié),修改字節(jié),修改mem_cfg.c,將,將app heap 的大小增加至少的大小增加至少44K。需要注意的是,如果要增大。需要注意的是,如果要增大heap,首先要確認一下當然,首先要確認一下當然ram是是 否還有這么多可用的空間,可以通過查看否還有這么多可用的空間,可以通過查看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)注的,可以看到當前就是我們要關(guān)注的,可以看到當前RW使用了使用了3851K,而,而RAM的總數(shù)的總數(shù) 是是4096K,所以還有充足的空間,所以還有充足的空間,heap增加個幾十增加個幾十K沒有什么問題。沒有什么問題。 可以看到使用可以看到使用2和和3都可以解決問題,通常把增大都可以解決問題,通常把增大heap作為最后的手段。作為最后的手段。 保密

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

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

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

溫馨提示

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

評論

0/150

提交評論