版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、MOCOR平台内存管理介绍及案例分析平台内存管理介绍及案例分析主讲人:GSM_FAE保密信息MOCOR平台内存管理介绍平台内存管理介绍MOCOR内存管理的基本架构内存管理的基本架构 ThreadX的内存管理的内存管理 MOCOR的内存管理的内存管理MOCOR内存内存bug实例分析实例分析 保密信息MOCOR内存管理的基本架构内存管理的基本架构一般的嵌入式系统中最基本的内存管理方案有两种静态分配和动态分配。静态分配是指在编译或链接时将程序所需的内存空间分配好。采用这种分配方案的内存段,其大小一般在编译时就能够确定。静态分配比较简单,一般不需要特殊的管理。动态分配是指系统运行时根据需要动态地分配内
2、存,为实现动态分配,系统里需要有一套完善的管理机制。本文中所指的内存管理,就是指动态分配内存的管理。保密信息MOCOR内存管理的基本架构内存管理的基本架构 MOCOR内存管理体系的一个大致的调用层次如下图所示: 保密信息MOCOR内存管理的基本架构内存管理的基本架构从可用的内存资源的角度,还可以得到下面的一个内存分配图。从可用的内存资源的角度,还可以得到下面的一个内存分配图。保密信息MOCOR平台内存管理介绍平台内存管理介绍MOCOR内存管理的基本架构内存管理的基本架构 ThreadX的内存管理的内存管理 MOCOR的内存管理的内存管理MOCOR内存内存bug实例分析实例分析 保密信息Thre
3、adX的内存管理的内存管理 内存字节池内存字节池BTYE POOL)内存块池内存块池BLOCK POOL)保密信息ThreadX的内存管理的内存管理内存字节池内存字节池BTYE POOL)保密信息ThreadX的内存管理的内存管理-内存字节池内存字节池u1.基本概念:基本概念:u内存字节池是一个连续的内存块。在字节池中,内存的内存字节池是一个连续的内存块。在字节池中,内存的分配以字节为单位,任意大小的内存都可以在字节池上分配以字节为单位,任意大小的内存都可以在字节池上分配受限于内存的容量)。分配受限于内存的容量)。u内存字节池类似于内存字节池类似于C语言里的堆语言里的堆(heap),所以,字节
4、池我,所以,字节池我们也可以把它叫做字节堆,代码里我们也可以看到创建们也可以把它叫做字节堆,代码里我们也可以看到创建的字节池通常以的字节池通常以heap来命名。但与一般意义上的堆的不来命名。但与一般意义上的堆的不同在于,同在于,ThreadX里的字节池可以有多个,里的字节池可以有多个,MOCOR平台平台也是利用了这一特性,根据不同的需求而创建了多个也是利用了这一特性,根据不同的需求而创建了多个heap。u每一个字节池都有一个相应的字节池控制块,通常是一每一个字节池都有一个相应的字节池控制块,通常是一个全局结构。控制块包括对内存池的定义和状态,比如个全局结构。控制块包括对内存池的定义和状态,比如
5、内存池的名字,可用的字节数等。该结构的定义如下:内存池的名字,可用的字节数等。该结构的定义如下:保密信息ThreadX的内存管理的内存管理-内存字节池内存字节池保密信息ThreadX的内存管理的内存管理-内存字节池内存字节池u2.分配方式:分配方式:u从字节池中分配内存类似于从字节池中分配内存类似于C语言的语言的malloc调用,该调用调用,该调用返回所需内存的数量以字节为单位)。分配的原则是返回所需内存的数量以字节为单位)。分配的原则是“首次符合准绳,就是说,当第一个空闲内存块的大首次符合准绳,就是说,当第一个空闲内存块的大小满足需求时,就从该内存块分配内存,然后将该内存小满足需求时,就从该
6、内存块分配内存,然后将该内存块的剩余内存转换成一个新块。字节池在初始状态下,块的剩余内存转换成一个新块。字节池在初始状态下,只有一个空闲块,以后随着随着分配的进行,内存块会只有一个空闲块,以后随着随着分配的进行,内存块会随之增多。随之增多。u 除了上述的分配原则之外,字节池里还定义了一个值除了上述的分配原则之外,字节池里还定义了一个值BYTE_POOL_SLIP_SIZE。这是在代码里实现指定的一。这是在代码里实现指定的一个具体数值,在分配内存时,如果要分配的内存大小大个具体数值,在分配内存时,如果要分配的内存大小大于这一数值,则从字节池的底部开始分配。采用这种分于这一数值,则从字节池的底部开
7、始分配。采用这种分配方式是为了减少内存碎片的产生,尽量把大内存的分配方式是为了减少内存碎片的产生,尽量把大内存的分配区域和小内存的分配区域分开。目前系统里定义的配区域和小内存的分配区域分开。目前系统里定义的BYTE_POOL_SLIP_SIZE为为80K。保密信息ThreadX的内存管理的内存管理-内存字节池内存字节池u3.内存布局:内存布局:u以一个分配了两次的字节池为例,在内存中的情况如下:以一个分配了两次的字节池为例,在内存中的情况如下:保密信息ThreadX的内存管理的内存管理-内存字节池内存字节池留意:留意:首先要注意的问题是碎片,一个字节池可能有首先要注意的问题是碎片,一个字节池可
8、能有2000字节的可用空间,但不保证一定能分字节的可用空间,但不保证一定能分配到配到2000字节的连续空间,内存池对连续字节的数量不做保证。字节的连续空间,内存池对连续字节的数量不做保证。分配一块内存所需要的时间跟分配内存的大小,字节池中的碎片数等因素有关,如果字分配一块内存所需要的时间跟分配内存的大小,字节池中的碎片数等因素有关,如果字节池有节池有2000字节的空闲块,花多长时间找到这块内存也是没有保证的。因此,在时间字节的空闲块,花多长时间找到这块内存也是没有保证的。因此,在时间要求苛刻的任务中应避免使用字节池。要求苛刻的任务中应避免使用字节池。 字节池不能在中断函数里使用,也不能在字节池
9、不能在中断函数里使用,也不能在timer回调函数里使用。回调函数里使用。保密信息ThreadX的内存管理的内存管理-内存字节池内存字节池思索:假定系统中有一个内存字节池,并且已经从中分配了几次内存。当内存池中还有500字节的剩余内存时,应用程序申请200字节的内存,在什么情况下,这样的申请不能满足?保密信息ThreadX的内存管理的内存管理内存块池内存块池BLOCK POOL)保密信息ThreadX的内存管理的内存管理-内存块池内存块池u1.基本概念:基本概念:u内存块池也是一个连续的字节块,但它是由一定数量的内存块池也是一个连续的字节块,但它是由一定数量的固定固定szie的内存块组成的。因此
10、,从一个内存块池中分配的内存块组成的。因此,从一个内存块池中分配出的内存总是固定大小的。出的内存总是固定大小的。u相比字节池,内存块池的两个主要优势是:相比字节池,内存块池的两个主要优势是:u没有碎片。因为内存块池是固定没有碎片。因为内存块池是固定size的块构成,所以没有的块构成,所以没有碎片的产生。碎片的产生。u分配和释放的速度很快。所需的时间相当于简单的链表分配和释放的速度很快。所需的时间相当于简单的链表操作,分配时不需要搜索整个内存块列表,它总是使用操作,分配时不需要搜索整个内存块列表,它总是使用链表头部的内存块来分配。链表头部的内存块来分配。u内存块池的主要缺点是缺乏灵活性。固定尺寸
11、既是它的内存块池的主要缺点是缺乏灵活性。固定尺寸既是它的优点也是它的缺点。如果一个内存块池的尺寸足够大,优点也是它的缺点。如果一个内存块池的尺寸足够大,可以满足用户最极限的内存分配需求,那么,这个内存可以满足用户最极限的内存分配需求,那么,这个内存块池上分配许多不同尺寸的内存会导致严重的内存浪费。块池上分配许多不同尺寸的内存会导致严重的内存浪费。一种解决办法是同时创建几个不同的内存块池,每个内一种解决办法是同时创建几个不同的内存块池,每个内存块池分别容纳不同尺寸的内存块。目前存块池分别容纳不同尺寸的内存块。目前MOCOR平台就平台就是这样做的,具体我们后面再讨论。是这样做的,具体我们后面再讨论
12、。u同字节池一样,内存块池也有一个控制块结构,其中有同字节池一样,内存块池也有一个控制块结构,其中有该内存块的相关信息,该结构如下:该内存块的相关信息,该结构如下:保密信息ThreadX的内存管理的内存管理-内存块池内存块池保密信息ThreadX的内存管理的内存管理-内存块池内存块池u2.分配方式:分配方式:u内存块池中分配内存是非常快的,主要得益于内存块池内存块池中分配内存是非常快的,主要得益于内存块池中的所有空闲内存块组成一个链表中的所有空闲内存块组成一个链表(即上面结构中的即上面结构中的tx_block_pool_available_list)。每次分配时只需要取链。每次分配时只需要取链
13、表头即可,无须遍历内存块池来找到空闲块。表头即可,无须遍历内存块池来找到空闲块。保密信息ThreadX的内存管理的内存管理-内存块池内存块池u3.内存布局:内存布局:保密信息ThreadX的内存管理的内存管理-内存块池内存块池思索如何计算一个内存块池所占用的物理内存大小?保密信息MOCOR平台内存管理介绍平台内存管理介绍MOCOR内存管理的基本架构内存管理的基本架构 ThreadX的内存管理的内存管理 MOCOR的内存管理的内存管理MOCOR内存内存bug实例分析实例分析 保密信息MOCOR内存管理内存管理 MOCOR平台在平台在ThreadX内存管理的基础上,又做了进一步的封装,内存管理的基
14、础上,又做了进一步的封装,这样可以更便于上层应用调用。前面我们已经了解了这样可以更便于上层应用调用。前面我们已经了解了ThreadX是如是如何对内存进行管理的,下面我们从底层来到上层,看一看何对内存进行管理的,下面我们从底层来到上层,看一看MOCOR是是如何利用如何利用Threadx的内存管理机制来建立自己的内存管理方式。的内存管理机制来建立自己的内存管理方式。 之之前的前的MOCOR文档里,将内存字节池称为堆文档里,将内存字节池称为堆heap),而将内存块),而将内存块池称为内存池池称为内存池pool),我们也延续这种说法,请注意不要混淆。我们也延续这种说法,请注意不要混淆。保密信息MOCO
15、R内存管理内存管理u1.堆内存堆内存(heap)管理管理:uMOCOR平台的堆内存就是前面讲到的内存字节池。最早平台的堆内存就是前面讲到的内存字节池。最早的的MOCOR平台只有一个内存堆,但在实际使用中发现,平台只有一个内存堆,但在实际使用中发现,程序运行时往往要交错的分配一些动态内存和常驻内存,程序运行时往往要交错的分配一些动态内存和常驻内存,这样会产生很多无法消除的内存碎片。同时这样会产生很多无法消除的内存碎片。同时base等通讯等通讯模块同上层应用又是并发的,这样无规律的分配也会造模块同上层应用又是并发的,这样无规律的分配也会造成很多内存碎片。为了解决这种情况,后来成很多内存碎片。为了解
16、决这种情况,后来MOCOR版本版本将内存堆分成了三块,也就是创建了三个内存字节池作将内存堆分成了三块,也就是创建了三个内存字节池作为为heap。这三个字节池的分别是:。这三个字节池的分别是:dynamic base heap,static heap和和dynamic app heap。同样,对应着。同样,对应着三个三个heap也有三个不同的接口,分别是也有三个不同的接口,分别是:uSCI_ALLOC_BASE,uSCI_ALLOC_CONSTuSCI_ALLOC_APP。保密信息MOCOR内存管理内存管理 三个三个heap: Base heap: 主要给主要给PS,Layer1等使用。这个等使
17、用。这个heap我们我们一般不用关心。一般不用关心。 Static heap:主要用于分配常驻的内存,即一旦分配就:主要用于分配常驻的内存,即一旦分配就不再释放的内存。不再释放的内存。 App heap: 其他不属于以上两种情况的内存都在这里分其他不属于以上两种情况的内存都在这里分配。配。保密信息MOCOR内存管理内存管理三个三个heap的大小都定义在的大小都定义在mem_cfg.c里:里:#define MAX_STATIC_HEAP_SIZE (600*1024)#define MAX_DYNAMIC_BASE_HEAP_SIZE (60*1024)#define MAX_DYNAMIC_
18、APP_HEAP_SIZE (1430 * 1024)#define BYTE_HEAP_SIZE (MAX_STATIC_HEAP_SIZE + MAX_DYNAMIC_BASE_HEAP_SIZE + MAX_DYNAMIC_APP_HEAP_SIZE)保密信息MOCOR内存管理内存管理系统系统assert之后,选择菜单之后,选择菜单5,可以看到所有,可以看到所有heap上的内存分配信息,上的内存分配信息,类似这样:类似这样:保密信息MOCOR内存管理内存管理思索:前面讲了MOCOR里有三个不同用途的heap,想一想哪些内存是要在static heap里分配的,如果这些内存改在app he
19、ap上会有什么问题?尝试举出几个实际的例子来说明。保密信息MOCOR内存管理内存管理u2.内存池管理:内存池管理:u这个所说的内存池这个所说的内存池(pool)就是特指前面提到的内存块池。就是特指前面提到的内存块池。之前我们提到过,为了避免浪费内存,通常是分配多个之前我们提到过,为了避免浪费内存,通常是分配多个内存池,分别对应不同的大小。内存池,分别对应不同的大小。MOCOR平台一共创建平台一共创建了了12个内存池,其对应的大小和包含的内存块的数目都个内存池,其对应的大小和包含的内存块的数目都定义在定义在mem_cfg.c里:里:u#define POOL_1_BLOCK_SIZE 16 /p
20、ools block sizeu#define POOL_1_BLOCK_NUM 480 /pools block numberu#define POOL_2_BLOCK_SIZE 24 /pools block size u#define POOL_2_BLOCK_NUM 320 /pools block number u#define POOL_3_BLOCK_SIZE 40 /pools block size u#define POOL_3_BLOCK_NUM 650 /pools block number u#define POOL_4_BLOCK_SIZE 60 /pools blo
21、ck size u#define POOL_4_BLOCK_NUM 500 /pools block number u#define POOL_5_BLOCK_SIZE 112 /pools block size u#define POOL_5_BLOCK_NUM 80 /pools block number u#define POOL_6_BLOCK_SIZE 180 /pools block size u#define POOL_6_BLOCK_NUM 280 /pools block number u#define POOL_7_BLOCK_SIZE 300 /pools block s
22、ize u#define POOL_7_BLOCK_NUM 80 /pools block number u#define POOL_8_BLOCK_SIZE 600 /pools block size u#define POOL_8_BLOCK_NUM 120 /pools block number u#define POOL_9_BLOCK_SIZE 800 /pools block size u#define POOL_9_BLOCK_NUM 100 /pools block number u#define POOL_A_BLOCK_SIZE 1100 /pools block size
23、 u#define POOL_A_BLOCK_NUM 98 /pools block number u#define POOL_B_BLOCK_SIZE 1300 /pools block size u#define POOL_B_BLOCK_NUM 10 /pools block number u#define POOL_C_BLOCK_SIZE 1600 /pools block size u#define POOL_C_BLOCK_NUM 12 /pools block number u(以上的定义不同版本的以上的定义不同版本的MOCOR可能并不一致,经常会可能并不一致,经常会有调整有调
24、整)保密信息MOCOR内存管理内存管理什么时候在什么时候在heap上分配,什么时候在内存池上分配?上分配,什么时候在内存池上分配?MOCOR对分配内存的位置有如下的约定:只有分配的内存的大小超过对分配内存的位置有如下的约定:只有分配的内存的大小超过mem_cfg.c里定义的最大的内存块池的大小,内存才会在里定义的最大的内存块池的大小,内存才会在heap里分里分配,否则就在内存块池里分配。目前配,否则就在内存块池里分配。目前MOCOR平台定义的最大的内存平台定义的最大的内存块池是块池是1600字节,也就是大于字节,也就是大于1600字节的内存才在字节的内存才在heap里分配。里分配。 保密信息M
25、OCOR内存管理内存管理MOCOR在内存池上的分配策略是:在内存池上的分配策略是:最小适配原则:按从小到大的顺序,遍历所有的内存池,直到找到一个内存池,其大最小适配原则:按从小到大的顺序,遍历所有的内存池,直到找到一个内存池,其大小大于欲分配内存的大小,就在该内存池分配内存。如果该内存池已被用尽,则继续小大于欲分配内存的大小,就在该内存池分配内存。如果该内存池已被用尽,则继续向下遍历,找到下一个适合的内存池。如果全部遍历完都没有找到可用的内存池,则向下遍历,找到下一个适合的内存池。如果全部遍历完都没有找到可用的内存池,则改为在改为在heap上分配内存。上分配内存。上面的策略对于上层的申请者是透
26、明的,申请者只要传入欲分配的内存大小即可,无上面的策略对于上层的申请者是透明的,申请者只要传入欲分配的内存大小即可,无须关心内存究竟是在哪里分配的。须关心内存究竟是在哪里分配的。保密信息MOCOR内存管理内存管理系统系统assert之后,选择菜单之后,选择菜单5,可以看到当前所有,可以看到当前所有pool的信息,类似的信息,类似这样:这样:保密信息MOCOR内存管理内存管理u3.内存内存Debug信息:信息:u为了方便在出现内存问题的时候调试,通常在分配内存为了方便在出现内存问题的时候调试,通常在分配内存的时候的时候(heap和和pool),会额外的多分配一个,会额外的多分配一个header,
27、放,放在每一块分配内存的开始。在每一块分配内存的开始。header的结构定义如下:的结构定义如下:u结构成员的意义如下:结构成员的意义如下:upre , succ : 两个指向两个指向header结构的指针,目的是将所有结构的指针,目的是将所有的的header串成一张双向链表。串成一张双向链表。ufile_name , line: 分配该块内存的文件名和行号分配该块内存的文件名和行号usize : 内存大小内存大小(不包括不包括header)ublock_num: 系统分配的内存块总计系统分配的内存块总计u此外,为了能检查内存越界,在每一块分配内存的最后此外,为了能检查内存越界,在每一块分配内
28、存的最后也会额外多分配一个字节做为也会额外多分配一个字节做为END FLAG,内存分配时,内存分配时该字节会被写入该字节会被写入0 xAA。当该内存被释放时,会检查该标。当该内存被释放时,会检查该标志位,如果不为志位,如果不为0 xAA,则说明出现异常,系统,则说明出现异常,系统ASSERT。保密信息MOCOR内存管理内存管理加入加入debug信息后的内存如下:信息后的内存如下:保密信息MOCOR内存管理内存管理 因为有额外加了这些因为有额外加了这些debug信息,所以如果我们要分配信息,所以如果我们要分配N个字节的内个字节的内存,那么实际上分配的大小是存,那么实际上分配的大小是:N + si
29、zeof(MEM_HEADER_T) + 1.再再考虑到字节对齐的需要,实际的空间比上面的数字可能还要大一点。考虑到字节对齐的需要,实际的空间比上面的数字可能还要大一点。 比如比如16字节的内存池,其中每个内存块的大小其实是:字节的内存池,其中每个内存块的大小其实是:16 + 24 + 4 (本应是加本应是加1,加,加4是为了字节对齐是为了字节对齐) Header里的里的pre指向前一块分配的内存,指向前一块分配的内存,next指向后一块分配的内指向后一块分配的内存,所有分配的内存,都通过存,所有分配的内存,都通过header里的里的pre和和succ指针串起来,指针串起来,构成一张双向链表。
30、每分配一块新的内存,就将这块内存的构成一张双向链表。每分配一块新的内存,就将这块内存的header加到链表的最后。通过遍历加到链表的最后。通过遍历header构成的链表,我们可以得到当前构成的链表,我们可以得到当前所有分配的内存块的信息。所有分配的内存块的信息。保密信息MOCOR内存管理内存管理系统系统assert之后,选择菜单之后,选择菜单4,就可以打印出这些信息,类似这样,就可以打印出这些信息,类似这样:保密信息MOCOR内存管理内存管理 思索: 应用里分配一块大小为N字节的内存,实际在内存里占了多少空间?保密信息MOCOR内存管理内存管理 练习:练习: 前面我们已经讲了前面我们已经讲了M
31、OCOR平台各类内存的分配平台各类内存的分配情况,下面需要你亲自动手加深理解。使用我们情况,下面需要你亲自动手加深理解。使用我们的样机,连上的样机,连上log,主动,主动assert,输入,输入3,dump出出当前的内存。输入当前的内存。输入5,打出当前的内存信息。然,打出当前的内存信息。然后打开内存后打开内存dump文件,找到文件,找到app heap的起始地的起始地址,从起始地址开始,推出整个址,从起始地址开始,推出整个app heap的所的所有内存块的信息,然后用刚才打印出的信息验证有内存块的信息,然后用刚才打印出的信息验证一下你的推导是否正确。一下你的推导是否正确。保密信息MOCOR内
32、存管理内存管理u4.物理内存:物理内存:u内存管理的最终的对象就是物理内存,但是,物理内存内存管理的最终的对象就是物理内存,但是,物理内存并不能全部用于动态分配,因为一些全局变量,代码等并不能全部用于动态分配,因为一些全局变量,代码等需要占用物理内存,这些相当于静态分配。而我们通常需要占用物理内存,这些相当于静态分配。而我们通常说的内存管理是指动态的对内存进行分配和释放。那么说的内存管理是指动态的对内存进行分配和释放。那么哪些物理内存是我们能够动态分配使用的呢,我们是如哪些物理内存是我们能够动态分配使用的呢,我们是如何知道可以动态分配的物理内存的地址范围呢?何知道可以动态分配的物理内存的地址范
33、围呢?u以以6600L芯片为例,芯片为例,L所用的所用的NORMCP中的中的SRAM通常是通常是4M,这,这4M就是我们所能够用到的所有物理内存。就是我们所能够用到的所有物理内存。OS启启动后,会把物理内存动后,会把物理内存SRAM的地址映射到的地址映射到0 x04000000到到0 x04400000这个区域。这个区域。保密信息MOCOR内存管理内存管理Heap和和pool对应的物理内存的位置和大小:对应的物理内存的位置和大小:uint32 pool_1_addrPOOL_XX_SIZE(POOL_1_BLOCK_SIZE, POOL_1_BLOCK_NUM);uint32 pool_2_a
34、ddrPOOL_XX_SIZE(POOL_2_BLOCK_SIZE, POOL_2_BLOCK_NUM);uint32 pool_3_addrPOOL_XX_SIZE(POOL_3_BLOCK_SIZE, POOL_3_BLOCK_NUM);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 ; 保密
35、信息MOCOR内存管理内存管理u5.内存委托管理:内存委托管理:u委托内存管理实质就是给了模块创建自己的委托内存管理实质就是给了模块创建自己的heap和和pool的机会。通常情况下我们使用的的机会。通常情况下我们使用的heap和和pool都是系统创都是系统创建的。但有些模块也想先从系统的建的。但有些模块也想先从系统的heap里分出一块大内里分出一块大内存,然后在这块大内存上,再根据自己的需要细分出一存,然后在这块大内存上,再根据自己的需要细分出一些内存块来供本模块使用。在没有委托内存管理之前,些内存块来供本模块使用。在没有委托内存管理之前,这种细分的工作实际由各模块自己来完成,实现的手法这种细
36、分的工作实际由各模块自己来完成,实现的手法也五花八门。有了委托内存管理,模块可以在分配的大也五花八门。有了委托内存管理,模块可以在分配的大内存的基础上,再创建自己的内存的基础上,再创建自己的heap和和pool,这些,这些heap和和pool的实现机制,同我们之前讲的系统的机制是基本一的实现机制,同我们之前讲的系统的机制是基本一样的。样的。保密信息MOCOR内存管理内存管理u6.BLOCK MEM:u关于关于BLOCK MEM可以参考可以参考的第二章,如果还不清楚的第二章,如果还不清楚block mem的目的和用法的目的和用法的,请务必先学习上面这篇文档。的,请务必先学习上面这篇文档。保密信息
37、MOCOR内存管理内存管理几个容易混淆的地方:几个容易混淆的地方:1. BLOCK MEM并不是在内存中实际分配出一块区域来进行管理并不是在内存中实际分配出一块区域来进行管理虽然旧的虽然旧的MOCOR版本上确实是这样的),版本上确实是这样的),BLOCK MEM的分配的分配依然是在依然是在app heap上完成的。既然是在上完成的。既然是在app heap上分配的,那么上分配的,那么assert之后按之后按5,从,从app heap的信息里是可以找到当前分配的的信息里是可以找到当前分配的block mem的,比如这样:的,比如这样:保密信息MOCOR内存管理内存管理保密信息MOCOR内存管理内
38、存管理2.BLOCK MEM的管理机制中,为各块的管理机制中,为各块mem都定义了一个都定义了一个offset,但这,但这个个offset纯粹是一个逻辑概念,它的作用是在分配纯粹是一个逻辑概念,它的作用是在分配block mem时判时判断是否存在断是否存在mem冲突。一个冲突。一个block在内存中的实际位置同这个在内存中的实际位置同这个offset没有任何关系。没有任何关系。保密信息MOCOR内存管理内存管理MOCOR内存管理的基本架构内存管理的基本架构 ThreadX的内存管理的内存管理 MOCOR的内存管理的内存管理MOCOR内存内存bug实例分析实例分析保密信息MOCOR内存内存bug
39、实例分析实例分析内存不足内存不足: 内存不足是经常遇到的问题,内内存不足是经常遇到的问题,内存不足根据产生的原因,还可以分为存不足根据产生的原因,还可以分为内存泄露引起的不足,内存碎片引起内存泄露引起的不足,内存碎片引起的不足,以及真正的内存不足。下面的不足,以及真正的内存不足。下面我们以几个具体的例子来分析。我们以几个具体的例子来分析。保密信息MOCOR内存内存bug实例分析实例分析u1.内存泄漏:内存泄漏:u内存泄露是指分配了一块内存在使用完后却没有释放,内存泄露是指分配了一块内存在使用完后却没有释放,造成系统中可用内存越来越少,最后死机。内存泄露引造成系统中可用内存越来越少,最后死机。内
40、存泄露引起的死机很容易定位,只要在死机后输入起的死机很容易定位,只要在死机后输入4,打出当前所,打出当前所有分配的内存信息,查看是否有大量的重复的内存分配有分配的内存信息,查看是否有大量的重复的内存分配就可以知道。就可以知道。u实例:某客户项目,测试中反复拨号出现死机,死机信实例:某客户项目,测试中反复拨号出现死机,死机信息为:息为:uFile: RTOSsourcesrccthreadx_mem.cuLine: 494uASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), mmipb_wintab.c, line=1155
41、0, param=0 x4650)u打出当前所有分配的信息,发现异常打出当前所有分配的信息,发现异常,有一条分配信息出有一条分配信息出现多次:现多次:保密信息MOCOR内存内存bug实例分析实例分析保密信息MOCOR内存内存bug实例分析实例分析u2.内存碎片:内存碎片:u如果系统中存在内存碎片,可能会出现虽然剩余的总内如果系统中存在内存碎片,可能会出现虽然剩余的总内存数是足够的,但依然分配不出内存的情况。存数是足够的,但依然分配不出内存的情况。u实例,某客户项目,后台运行实例,某客户项目,后台运行QQ,进入,进入DC后死机。后死机。uFile: RTOSsourcesrccthreadx_m
42、em.cuLine: 494uASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), block_mem.c, line=563, param=0 x113004)u从死机信息可以看出,要分配的内存大小为从死机信息可以看出,要分配的内存大小为0 x1130041126404),这么大的内存只可能从),这么大的内存只可能从heap上分配,查上分配,查看看app heap的信息如下:的信息如下:保密信息MOCOR内存内存bug实例分析实例分析保密信息MOCOR内存内存bug实例分析实例分析我们重点关注画红圈的三块内存,可以看到,剩
43、余的总内存我们重点关注画红圈的三块内存,可以看到,剩余的总内存1495344,大于欲分配的内存,但是,大于欲分配的内存,但是编号编号1和和3的两块空闲内存正好被编号的两块空闲内存正好被编号2的内存隔开了,的内存隔开了,1,和和3的大小都不超过的大小都不超过1126404,所以无法,所以无法分配,这就是一个典型的内存碎片造成内存不足的场景。要解决这个问题,我们就要想办法把两分配,这就是一个典型的内存碎片造成内存不足的场景。要解决这个问题,我们就要想办法把两块空闲内存连在一起,主要就是要调整这几块内存的分配和释放的顺序。我们不妨用逆向思维来块空闲内存连在一起,主要就是要调整这几块内存的分配和释放的
44、顺序。我们不妨用逆向思维来分析,先看一下造成内存碎片的顺序是怎样的,然后我们只要避免这种顺序就可以了。首先在最分析,先看一下造成内存碎片的顺序是怎样的,然后我们只要避免这种顺序就可以了。首先在最初时,初时,1,2,3这三块内存实际是一整块空闲内存。前面我们提过,字节池分配内存时有一个反向分这三块内存实际是一整块空闲内存。前面我们提过,字节池分配内存时有一个反向分配的概念,当要分配的的内存大于配的概念,当要分配的的内存大于80K时,是从底向上分配的。所以分配和释放的顺序是:时,是从底向上分配的。所以分配和释放的顺序是:第一步:分配内存第一步:分配内存3;第二步:分配内存第二步:分配内存2;第三步
45、:释放内存第三步:释放内存3由此可以自然的想到解决的办法,就是调整上面的由此可以自然的想到解决的办法,就是调整上面的3个步骤,具体可以有两种办法:个步骤,具体可以有两种办法:内存块内存块2先于先于3分配,这样分配,这样3释放后自然同释放后自然同1连在一起。连在一起。内存块内存块2在在3释放之后再分配,这样释放之后再分配,这样2占了内存占了内存3的位置,剩余的内存也是连续的。的位置,剩余的内存也是连续的。具体用什么方法,就要根据实际的具体情况,看哪一种方法是最可行的。在客户的这个问题中,具体用什么方法,就要根据实际的具体情况,看哪一种方法是最可行的。在客户的这个问题中,内存块内存块3是一个第三方
46、桌面插件分配的,内存块是一个第三方桌面插件分配的,内存块2是是QQ分配的。所以第分配的。所以第2种方法最可行,在分配种方法最可行,在分配QQ的内存前,先释放掉第三方桌面插件的内存,问题由此解决。的内存前,先释放掉第三方桌面插件的内存,问题由此解决。保密信息MOCOR内存内存bug实例分析实例分析留意:留意: 并不是所有的内存碎片问题都能够通过这并不是所有的内存碎片问题都能够通过这样的调整来得到解决。系统运行的过程中,一些样的调整来得到解决。系统运行的过程中,一些内存碎片的产生是无法避免的,这种情况下内存内存碎片的产生是无法避免的,这种情况下内存碎片无法得到消除或消除的难度很大。碎片无法得到消除
47、或消除的难度很大。保密信息MOCOR内存内存bug实例分析实例分析u3.实际内存不足:实际内存不足:u如果出现剩余的内存不够分配,此时查看内存分配的情如果出现剩余的内存不够分配,此时查看内存分配的情况也没有异常也就是说已经排除了内存泄露和碎片的况也没有异常也就是说已经排除了内存泄露和碎片的原因),这种情况就是真正的内存不足了。遇到这种情原因),这种情况就是真正的内存不足了。遇到这种情况,一般有这些思路:况,一般有这些思路:u要求客户裁剪功能,减少内存的使用,通常客户会对平要求客户裁剪功能,减少内存的使用,通常客户会对平台版本进行一些定制,比如增加一些第三方应用等等,台版本进行一些定制,比如增加
48、一些第三方应用等等,这些新增的模块往往会造成内存使用的增加。这些新增的模块往往会造成内存使用的增加。u如果某些操作很耗内存,那么执行这些操作时最好将其如果某些操作很耗内存,那么执行这些操作时最好将其他操作退出,尽量避免并发。他操作退出,尽量避免并发。u以上都不行的话最后只能通过增大以上都不行的话最后只能通过增大heap size来解决。来解决。保密信息MOCOR内存内存bug实例分析实例分析某客户上报问题,进文件管理器,选择一张某客户上报问题,进文件管理器,选择一张gif图片发彩信图片发彩信时出现内存不足死机:时出现内存不足死机:File: RTOSsourcesrccthreadx_mem.
49、cLine: 494ASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), block_mem.c, line=521, param=0 x25804)从上面的信息可以看到欲分配的内存大小是从上面的信息可以看到欲分配的内存大小是0 x25804(153604)。查看查看app heap的使用情况如下的使用情况如下保密信息MOCOR内存内存bug实例分析实例分析保密信息MOCOR内存内存bug实例分析实例分析 可以看到当前剩余的总内存也不过是可以看到当前剩余的总内存也不过是141744,其中最大一块空闲内存是,其中最大一块空闲内
50、存是0 x1aa4c(109132),还差,还差0 x25804-0 x1aa4c = 0 xADB844472才够分配。才够分配。我们用刚才的几种思路分析一下:我们用刚才的几种思路分析一下:裁剪功能,因为没有第三方的东西,这个不考虑裁剪功能,因为没有第三方的东西,这个不考虑避免并发。通过分析内存,可以看到分配的内存实际上可以分为两大块见上图),一避免并发。通过分析内存,可以看到分配的内存实际上可以分为两大块见上图),一块是上面红框的部分,主要是由块是上面红框的部分,主要是由FMM分配的。另一块是下面红框部分,主要是由分配的。另一块是下面红框部分,主要是由MMS分配,所以这里存在分配,所以这里
51、存在MMS和和FMM并发的情况。如果我们在发送彩信之前就先退并发的情况。如果我们在发送彩信之前就先退出出FMM的话,可以解决此问题。的话,可以解决此问题。增大增大heap。前面我们已经算出当前差了。前面我们已经算出当前差了44472字节,修改字节,修改mem_cfg.c,将,将app heap的大的大小增加至少小增加至少44K。需要注意的是,如果要增大。需要注意的是,如果要增大heap,首先要确认一下当然,首先要确认一下当然ram是否还是否还有这么多可用的空间,可以通过查看有这么多可用的空间,可以通过查看map文件最后的几行信息:文件最后的几行信息: Total RO Size(Code +
52、RO Data) 7530419 (7353.92kB) Total RW Size(RW Data + ZI Data) 3944375 (3851.93kB) Total ROM Size(Code + RO Data + RW Data) 7586078 (7408.28kB) 红色的红色的RW size就是我们要关注的,可以看到当前就是我们要关注的,可以看到当前RW使用了使用了3851K,而,而RAM的总数的总数是是4096K,所以还有充足的空间,所以还有充足的空间,heap增加个几十增加个几十K没有什么问题。没有什么问题。 可以看到使用可以看到使用2和和3都可以解决问题,通常把增大都
53、可以解决问题,通常把增大heap作为最后的手段。作为最后的手段。 保密信息MOCOR内存内存bug实例分析实例分析内存覆盖:内存覆盖: 内存覆盖也是常见的一类内存内存覆盖也是常见的一类内存问题,引起内存覆盖的原因很多,往问题,引起内存覆盖的原因很多,往往没有固定规律可循。而且有时出现往没有固定规律可循。而且有时出现覆盖后并不立刻死机,这样无法确认覆盖后并不立刻死机,这样无法确认第一现场,增大了解决问题的难度。第一现场,增大了解决问题的难度。但在但在MOCOR平台下,我们有一个非平台下,我们有一个非常有用的工具:常有用的工具:Bus Monitor。利用。利用Bus Monitor后文简称后文简
54、称BM),我们),我们有一个解决覆盖问题的一般性思路:有一个解决覆盖问题的一般性思路:首先确定被覆盖内存的地址首先确定被覆盖内存的地址(可能是一可能是一个地址范围个地址范围),如果问题可以重现,且,如果问题可以重现,且每次被覆盖的地址比较固定,则可以每次被覆盖的地址比较固定,则可以用用BM监控被覆盖的地址,这样当内存监控被覆盖的地址,这样当内存被覆盖时会第一时间死机,可以迅速被覆盖时会第一时间死机,可以迅速定位。定位。Bus Monitor的用法比较简单,的用法比较简单,可以参考相关文档。可以参考相关文档。保密信息MOCOR内存内存bug实例分析实例分析u1.案例一案例一u 内存写入时越界是出
55、现内存覆盖的一个常见原因,内存写入时越界是出现内存覆盖的一个常见原因,相对来说也比较好查的,只要找到越界的那块内存基本相对来说也比较好查的,只要找到越界的那块内存基本就可以定位,我们看下面的例子:就可以定位,我们看下面的例子:u客户项目发现进入电话本偶而会出现死机,死机现场:客户项目发现进入电话本偶而会出现死机,死机现场:uFile: RTOSsourcesrccthreadx_mem.cuLine: 364uASSERT(ASSERT: Error 0 x10 (No memory, unable to allocate !), wdp_customer.c, line=2098, para
56、m=0 xFA4)u初一看好像是个内存不足的,但实际不是,初一看好像是个内存不足的,但实际不是,assert界面界面输入输入4后打出当前分配的内存,就会发现有错误:后打出当前分配的内存,就会发现有错误:保密信息MOCOR内存内存bug实例分析实例分析保密信息MOCOR内存内存bug实例分析实例分析 可以看到最后一行可以看到最后一行“memory is corrupted”,表明在遍历,表明在遍历mem header的链表时出错,这意味着某一块的链表时出错,这意味着某一块memory的的header异异常了,而且这块内存的地址是常了,而且这块内存的地址是0 x40bcc30。Assert界面输入界面输入3,dump出当前内存后,我们打开出当前内存后,我们打开dump文件,找到文件,找到0 x00bcc3
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 品牌资产评价师冲突管理能力考核试卷含答案
- 珍珠岩加工工岗前规章考核试卷含答案
- 平板显示膜涂布工岗前持续改进考核试卷含答案
- 裁剪服装制版师安全知识宣贯能力考核试卷含答案
- 野生动物疫病防治工岗前能力评估考核试卷含答案
- 煤焦车司机岗前保密考核试卷含答案
- 预见性护理与多学科合作
- 2026钣金件建模面试题及答案
- 2026百度竞价面试题及答案大全解析
- 分级护理的护士角色
- 面粉粉尘爆炸应急演练预案
- 烟化炉车间技术、安全及设备维护保养手册
- 国家OTC药品目录(全部品种)
- 2023学年完整公开课版东南亚4
- 川2020J146-TJ 建筑用轻质隔墙条板构造图集
- 空气预热器检修工艺标准
- 测井沉积相课件
- 安全生产组织架构
- 超前钻勘查工程合同
- 弱电智能化工程施工组织设计方案方案
- LY/T 1697-2007饰面木质墙板
评论
0/150
提交评论