MOCOR平台内存管理介绍及案例分析.ppt

上传人:牧羊曲112 文档编号:5440304 上传时间:2023-07-07 格式:PPT 页数:68 大小:1.44MB
返回 下载 相关 举报
MOCOR平台内存管理介绍及案例分析.ppt_第1页
第1页 / 共68页
MOCOR平台内存管理介绍及案例分析.ppt_第2页
第2页 / 共68页
MOCOR平台内存管理介绍及案例分析.ppt_第3页
第3页 / 共68页
MOCOR平台内存管理介绍及案例分析.ppt_第4页
第4页 / 共68页
MOCOR平台内存管理介绍及案例分析.ppt_第5页
第5页 / 共68页
点击查看更多>>
资源描述

《MOCOR平台内存管理介绍及案例分析.ppt》由会员分享,可在线阅读,更多相关《MOCOR平台内存管理介绍及案例分析.ppt(68页珍藏版)》请在三一办公上搜索。

1、MOCOR平台内存管理介绍及案例分析,主讲人:GSM_FAE,.2,2023/7/7,MOCOR平台内存管理介绍,MOCOR内存管理的基本架构 ThreadX的内存管理 MOCOR的内存管理MOCOR内存bug实例分析,.3,2023/7/7,MOCOR内存管理的基本架构,一般的嵌入式系统中最基本的内存管理方案有两种静态分配和动态分配。静态分配是指在编译或链接时将程序所需的内存空间分配好。采用这种分配方案的内存段,其大小一般在编译时就能够确定。静态分配比较简单,一般不需要特殊的管理。动态分配是指系统运行时根据需要动态地分配内存,为实现动态分配,系统里需要有一套完善的管理机制。本文中所指的内存管

2、理,就是指动态分配内存的管理。,.4,2023/7/7,MOCOR内存管理的基本架构,MOCOR内存管理体系的一个大致的调用层次如下图所示:,.5,2023/7/7,MOCOR内存管理的基本架构,从可用的内存资源的角度,还可以得到下面的一个内存分配图。,.6,2023/7/7,MOCOR平台内存管理介绍,MOCOR内存管理的基本架构 ThreadX的内存管理 MOCOR的内存管理MOCOR内存bug实例分析,.7,2023/7/7,ThreadX的内存管理,内存字节池(BTYE POOL)内存块池(BLOCK POOL),.8,2023/7/7,ThreadX的内存管理,内存字节池(BTYE

3、POOL),.9,2023/7/7,ThreadX的内存管理-内存字节池,1.基本概念:内存字节池是一个连续的内存块。在字节池中,内存的分配以字节为单位,任意大小的内存都可以在字节池上分配(受限于内存的容量)。内存字节池类似于C语言里的堆(heap),所以,字节池我们也可以把它叫做字节堆,代码里我们也可以看到创建的字节池通常以heap来命名。但与一般意义上的堆的不同在于,ThreadX里的字节池可以有多个,MOCOR平台也是利用了这一特性,根据不同的需求而创建了多个heap。每一个字节池都有一个相应的字节池控制块,通常是一个全局结构。控制块包括对内存池的定义和状态,比如内存池的名字,可用的字节

4、数等。该结构的定义如下:,.10,2023/7/7,ThreadX的内存管理-内存字节池,.11,2023/7/7,ThreadX的内存管理-内存字节池,2.分配方式:从字节池中分配内存类似于C语言的malloc调用,该调用返回所需内存的数量(以字节为单位)。分配的原则是“首次符合”原则,就是说,当第一个空闲内存块的大小满足需求时,就从该内存块分配内存,然后将该内存块的剩余内存转换成一个新块。字节池在初始状态下,只有一个空闲块,以后随着随着分配的进行,内存块会随之增多。除了上述的分配原则之外,字节池里还定义了一个值BYTE_POOL_SLIP_SIZE。这是在代码里实现指定的一个具体数值,在分

5、配内存时,如果要分配的内存大小大于这一数值,则从字节池的底部开始分配。采用这种分配方式是为了减少内存碎片的产生,尽量把大内存的分配区域和小内存的分配区域分开。目前系统里定义的BYTE_POOL_SLIP_SIZE为80K。,.12,2023/7/7,ThreadX的内存管理-内存字节池,3.内存布局:以一个分配了两次的字节池为例,在内存中的情况如下:,.13,2023/7/7,ThreadX的内存管理-内存字节池,注意:首先要注意的问题是碎片,一个字节池可能有2000字节的可用空间,但不保证一定能分配到2000字节的连续空间,内存池对连续字节的数量不做保证。分配一块内存所需要的时间跟分配内存的

6、大小,字节池中的碎片数等因素有关,如果字节池有2000字节的空闲块,花多长时间找到这块内存也是没有保证的。因此,在时间要求苛刻的任务中应避免使用字节池。字节池不能在中断函数里使用,也不能在timer回调函数里使用。,.14,2023/7/7,ThreadX的内存管理-内存字节池,思考:假定系统中有一个内存字节池,并且已经从中分配了几次内存。当内存池中还有500字节的剩余内存时,应用程序申请200字节的内存,在什么情况下,这样的申请不能满足?,.15,2023/7/7,ThreadX的内存管理,内存块池(BLOCK POOL),.16,2023/7/7,ThreadX的内存管理-内存块池,1.基

7、本概念:内存块池也是一个连续的字节块,但它是由一定数量的固定szie的内存块组成的。因此,从一个内存块池中分配出的内存总是固定大小的。相比字节池,内存块池的两个主要优势是:没有碎片。因为内存块池是固定size的块构成,所以没有碎片的产生。分配和释放的速度很快。所需的时间相当于简单的链表操作,分配时不需要搜索整个内存块列表,它总是使用链表头部的内存块来分配。内存块池的主要缺点是缺乏灵活性。固定尺寸既是它的优点也是它的缺点。如果一个内存块池的尺寸足够大,可以满足用户最极限的内存分配需求,那么,这个内存块池上分配许多不同尺寸的内存会导致严重的内存浪费。一种解决办法是同时创建几个不同的内存块池,每个内

8、存块池分别容纳不同尺寸的内存块。目前MOCOR平台就是这样做的,具体我们后面再讨论。同字节池一样,内存块池也有一个控制块结构,其中有该内存块的相关信息,该结构如下:,.17,2023/7/7,ThreadX的内存管理-内存块池,.18,2023/7/7,ThreadX的内存管理-内存块池,2.分配方式:内存块池中分配内存是非常快的,主要得益于内存块池中的所有空闲内存块组成一个链表(即上面结构中的tx_block_pool_available_list)。每次分配时只需要取链表头即可,无须遍历内存块池来找到空闲块。,.19,2023/7/7,ThreadX的内存管理-内存块池,3.内存布局:,.

9、20,2023/7/7,ThreadX的内存管理-内存块池,思考如何计算一个内存块池所占用的物理内存大小?,.21,2023/7/7,MOCOR平台内存管理介绍,MOCOR内存管理的基本架构 ThreadX的内存管理 MOCOR的内存管理MOCOR内存bug实例分析,.22,2023/7/7,MOCOR内存管理,MOCOR平台在ThreadX内存管理的基础上,又做了进一步的封装,这样可以更便于上层应用调用。前面我们已经了解了ThreadX是如何对内存进行管理的,下面我们从底层来到上层,看一看MOCOR是如何利用Threadx的内存管理机制来建立自己的内存管理方式。之前的MOCOR文档里,将内存

10、字节池称为堆(heap),而将内存块池称为内存池(pool),我们也延续这种说法,请注意不要混淆。,.23,2023/7/7,MOCOR内存管理,1.堆内存(heap)管理:MOCOR平台的堆内存就是前面讲到的内存字节池。最早的MOCOR平台只有一个内存堆,但在实际使用中发现,程序运行时往往要交错的分配一些动态内存和常驻内存,这样会产生很多无法消除的内存碎片。同时base等通讯模块同上层应用又是并发的,这样无规律的分配也会造成很多内存碎片。为了解决这种情况,后来MOCOR版本将内存堆分成了三块,也就是创建了三个内存字节池作为heap。这三个字节池的分别是:dynamic base heap,s

11、tatic heap和dynamic app heap。同样,对应着三个heap也有三个不同的接口,分别是:SCI_ALLOC_BASE,SCI_ALLOC_CONSTSCI_ALLOC_APP。,.24,2023/7/7,MOCOR内存管理,三个heap:Base heap:主要给PS,Layer1等使用。这个heap我们一般不用关心。Static heap:主要用于分配常驻的内存,即一旦分配就不再释放的内存。App heap:其他不属于以上两种情况的内存都在这里分配。,.25,2023/7/7,MOCOR内存管理,三个heap的大小都定义在mem_cfg.c里:#define MAX_ST

12、ATIC_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),.26,2023/7/7,MOCOR内存管理,系统assert之后,选择菜单5,可以看到所有heap上的内存分配信息,类似这样:,.27,2023/7/7,MOCOR内存管理,思考:

13、前面讲了MOCOR里有三个不同用途的heap,想一想哪些内存是要在static heap里分配的,如果这些内存改在app heap上会有什么问题?尝试举出几个实际的例子来说明。,.28,2023/7/7,MOCOR内存管理,2.内存池管理:这个所说的内存池(pool)就是特指前面提到的内存块池。之前我们提到过,为了避免浪费内存,通常是分配多个内存池,分别对应不同的大小。MOCOR平台一共创建了12个内存池,其对应的大小和包含的内存块的数目都定义在mem_cfg.c里:#define POOL_1_BLOCK_SIZE 16/pools block size#define POOL_1_BLOC

14、K_NUM 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/pools block nu

15、mber#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 number#define POOL_8_BLOC

16、K_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#define POOL_B_BLOCK_SIZE 1300/pools blo

17、ck 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可能并不一致,经常会有调整),.29,2023/7/7,MOCOR内存管理,什么时候在heap上分配,什么时候在内存池上分配?MOCOR对分配内存的位置有如下的约定:只有分配的内存的大小超过mem_cfg.c里定义的最大的内存块池的大小,内存才会在heap里分配,否则就在内存

18、块池里分配。目前MOCOR平台定义的最大的内存块池是1600字节,也就是大于1600字节的内存才在heap里分配。,.30,2023/7/7,MOCOR内存管理,MOCOR在内存池上的分配策略是:最小适配原则:按从小到大的顺序,遍历所有的内存池,直到找到一个内存池,其大小大于欲分配内存的大小,就在该内存池分配内存。如果该内存池已被用尽,则继续向下遍历,找到下一个适合的内存池。如果全部遍历完都没有找到可用的内存池,则改为在heap上分配内存。上面的策略对于上层的申请者是透明的,申请者只要传入欲分配的内存大小即可,无须关心内存究竟是在哪里分配的。,.31,2023/7/7,MOCOR内存管理,系统

19、assert之后,选择菜单5,可以看到当前所有pool的信息,类似这样:,.32,2023/7/7,MOCOR内存管理,3.内存Debug信息:为了方便在出现内存问题的时候调试,通常在分配内存的时候(heap和pool),会额外的多分配一个header,放在每一块分配内存的开始。header的结构定义如下:结构成员的意义如下:pre,succ:两个指向header结构的指针,目的是将所有的header串成一张双向链表。file_name,line:分配该块内存的文件名和行号size:内存大小(不包括header)block_num:系统分配的内存块总计此外,为了能检查内存越界,在每一块分配内存

20、的最后也会额外多分配一个字节做为END FLAG,内存分配时该字节会被写入0 xAA。当该内存被释放时,会检查该标志位,如果不为0 xAA,则说明出现异常,系统ASSERT。,.33,2023/7/7,MOCOR内存管理,加入debug信息后的内存如下:,.34,2023/7/7,MOCOR内存管理,因为有额外加了这些debug信息,所以如果我们要分配N个字节的内存,那么实际上分配的大小是:N+sizeof(MEM_HEADER_T)+1.再考虑到字节对齐的需要,实际的空间比上面的数字可能还要大一点。比如16字节的内存池,其中每个内存块的大小其实是:16+24+4(本应是加1,加4是为了字节对

21、齐)Header里的pre指向前一块分配的内存,next指向后一块分配的内存,所有分配的内存,都通过header里的pre和succ指针串起来,构成一张双向链表。每分配一块新的内存,就将这块内存的header加到链表的最后。通过遍历header构成的链表,我们可以得到当前所有分配的内存块的信息。,.35,2023/7/7,MOCOR内存管理,系统assert之后,选择菜单4,就可以打印出这些信息,类似这样:,.36,2023/7/7,MOCOR内存管理,思考:应用里分配一块大小为N字节的内存,实际在内存里占了多少空间?,.37,2023/7/7,MOCOR内存管理,练习:前面我们已经讲了MOC

22、OR平台各类内存的分配情况,下面需要你亲自动手加深理解。使用我们的样机,连上log,主动assert,输入3,dump出当前的内存。输入5,打出当前的内存信息。然后打开内存dump文件,找到app heap的起始地址,从起始地址开始,推出整个app heap的所有内存块的信息,然后用刚才打印出的信息验证一下你的推导是否正确。,.38,2023/7/7,MOCOR内存管理,4.物理内存:内存管理的最终的对象就是物理内存,但是,物理内存并不能全部用于动态分配,因为一些全局变量,代码等需要占用物理内存,这些相当于静态分配。而我们通常说的内存管理是指动态的对内存进行分配和释放。那么哪些物理内存是我们能

23、够动态分配使用的呢,我们是如何知道可以动态分配的物理内存的地址范围呢?以6600L芯片为例,L所用的NORMCP中的SRAM通常是4M,这4M就是我们所能够用到的所有物理内存。OS启动后,会把物理内存SRAM的地址映射到0 x04000000到0 x04400000这个区域。,.39,2023/7/7,MOCOR内存管理,Heap和pool对应的物理内存的位置和大小:uint32 pool_1_addrPOOL_XX_SIZE(POOL_1_BLOCK_SIZE,POOL_1_BLOCK_NUM);uint32 pool_2_addrPOOL_XX_SIZE(POOL_2_BLOCK_SIZE

24、,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;,.40,2023/7/7,MOCOR内存管理,5.内存委托管理:委托内存管理实质

25、就是给了模块创建自己的heap和pool的机会。通常情况下我们使用的heap和pool都是系统创建的。但有些模块也想先从系统的heap里分出一块大内存,然后在这块大内存上,再根据自己的需要细分出一些内存块来供本模块使用。在没有委托内存管理之前,这种细分的工作实际由各模块自己来完成,实现的手法也五花八门。有了委托内存管理,模块可以在分配的大内存的基础上,再创建自己的heap和pool,这些heap和pool的实现机制,同我们之前讲的系统的机制是基本一样的。,.41,2023/7/7,MOCOR内存管理,6.BLOCK MEM:关于BLOCK MEM可以参考MOOCR应用模块内存使用接口的第二章,

26、如果还不清楚block mem的目的和用法的,请务必先学习上面这篇文档。,.42,2023/7/7,MOCOR内存管理,几个容易混淆的地方:1.BLOCK MEM并不是在内存中实际分配出一块区域来进行管理(虽然旧的MOCOR版本上确实是这样的),BLOCK MEM的分配依然是在app heap上完成的。既然是在app heap上分配的,那么assert之后按5,从app heap的信息里是可以找到当前分配的block mem的,比如这样:,.43,2023/7/7,MOCOR内存管理,.44,2023/7/7,MOCOR内存管理,2.BLOCK MEM的管理机制中,为各块mem都定义了一个of

27、fset,但这个offset纯粹是一个逻辑概念,它的作用是在分配block mem时判断是否存在mem冲突。一个block在内存中的实际位置同这个offset没有任何关系。,.45,2023/7/7,MOCOR内存管理,MOCOR内存管理的基本架构 ThreadX的内存管理 MOCOR的内存管理MOCOR内存bug实例分析,.46,2023/7/7,MOCOR内存bug实例分析,内存不足:内存不足是经常遇到的问题,内存不足根据产生的原因,还可以分为内存泄露引起的不足,内存碎片引起的不足,以及真正的内存不足。下面我们以几个具体的例子来分析。,.47,2023/7/7,MOCOR内存bug实例分析

28、,1.内存泄漏:内存泄露是指分配了一块内存在使用完后却没有释放,造成系统中可用内存越来越少,最后死机。内存泄露引起的死机很容易定位,只要在死机后输入4,打出当前所有分配的内存信息,查看是否有大量的重复的内存分配就可以知道。实例:某客户项目,测试中反复拨号出现死机,死机信息为:File:RTOSsourcesrccthreadx_mem.cLine:494ASSERT(ASSERT:Error 0 x10(No memory,unable to allocate!),mmipb_wintab.c,line=11550,param=0 x4650)打出当前所有分配的信息,发现异常,有一条分配信息出

29、现多次:,.48,2023/7/7,MOCOR内存bug实例分析,.49,2023/7/7,MOCOR内存bug实例分析,2.内存碎片:如果系统中存在内存碎片,可能会出现虽然剩余的总内存数是足够的,但依然分配不出内存的情况。实例,某客户项目,后台运行QQ,进入DC后死机。File:RTOSsourcesrccthreadx_mem.cLine:494ASSERT(ASSERT:Error 0 x10(No memory,unable to allocate!),block_mem.c,line=563,param=0 x113004)从死机信息可以看出,要分配的内存大小为0 x113004(1

30、126404),这么大的内存只可能从heap上分配,查看app heap的信息如下:,.50,2023/7/7,MOCOR内存bug实例分析,.51,2023/7/7,MOCOR内存bug实例分析,我们重点关注画红圈的三块内存,可以看到,剩余的总内存1495344,大于欲分配的内存,但是编号1和3的两块空闲内存正好被编号2的内存隔开了,1,和3的大小都不超过1126404,所以无法分配,这就是一个典型的内存碎片造成内存不足的场景。要解决这个问题,我们就要想办法把两块空闲内存连在一起,主要就是要调整这几块内存的分配和释放的顺序。我们不妨用逆向思维来分析,先看一下造成内存碎片的顺序是怎样的,然后我

31、们只要避免这种顺序就可以了。首先在最初时,1,2,3这三块内存实际是一整块空闲内存。前面我们提过,字节池分配内存时有一个反向分配的概念,当要分配的的内存大于80K时,是从底向上分配的。所以分配和释放的顺序是:第一步:分配内存3;第二步:分配内存2;第三步:释放内存3由此可以自然的想到解决的办法,就是调整上面的3个步骤,具体可以有两种办法:内存块2先于3分配,这样3释放后自然同1连在一起。内存块2在3释放之后再分配,这样2占了内存3的位置,剩余的内存也是连续的。具体用什么方法,就要根据实际的具体情况,看哪一种方法是最可行的。在客户的这个问题中,内存块3是一个第三方桌面插件分配的,内存块2是QQ分

32、配的。所以第2种方法最可行,在分配QQ的内存前,先释放掉第三方桌面插件的内存,问题由此解决。,.52,2023/7/7,MOCOR内存bug实例分析,注意:并不是所有的内存碎片问题都能够通过这样的调整来得到解决。系统运行的过程中,一些内存碎片的产生是无法避免的,这种情况下内存碎片无法得到消除或消除的难度很大。,.53,2023/7/7,MOCOR内存bug实例分析,3.实际内存不足:如果出现剩余的内存不够分配,此时查看内存分配的情况也没有异常(也就是说已经排除了内存泄露和碎片的原因),这种情况就是真正的内存不足了。遇到这种情况,一般有这些思路:要求客户裁剪功能,减少内存的使用,通常客户会对平台

33、版本进行一些定制,比如增加一些第三方应用等等,这些新增的模块往往会造成内存使用的增加。如果某些操作很耗内存,那么执行这些操作时最好将其他操作退出,尽量避免并发。以上都不行的话最后只能通过增大heap size来解决。,.54,2023/7/7,MOCOR内存bug实例分析,某客户上报问题,进文件管理器,选择一张gif图片发彩信时出现内存不足死机:File:RTOSsourcesrccthreadx_mem.cLine:494ASSERT(ASSERT:Error 0 x10(No memory,unable to allocate!),block_mem.c,line=521,param=0

34、x25804)从上面的信息可以看到欲分配的内存大小是0 x25804(153604)。查看app heap的使用情况如下,.55,2023/7/7,MOCOR内存bug实例分析,.56,2023/7/7,MOCOR内存bug实例分析,可以看到当前剩余的总内存也不过是141744,其中最大一块空闲内存是0 x1aa4c(109132),还差0 x25804-0 x1aa4c=0 xADB8(44472)才够分配。我们用刚才的几种思路分析一下:裁剪功能,因为没有第三方的东西,这个不考虑避免并发。通过分析内存,可以看到分配的内存实际上可以分为两大块(见上图),一块是上面红框的部分,主要是由FMM分配

35、的。另一块是下面红框部分,主要是由MMS分配,所以这里存在MMS和FMM并发的情况。如果我们在发送彩信之前就先退出FMM的话,可以解决此问题。增大heap。前面我们已经算出当前差了44472字节,修改mem_cfg.c,将app heap的大小增加至少44K。需要注意的是,如果要增大heap,首先要确认一下当然ram是否还有这么多可用的空间,可以通过查看map文件最后的几行信息:Total RO Size(Code+RO Data)7530419(7353.92kB)Total RW Size(RW Data+ZI Data)3944375(3851.93kB)Total ROM Size(C

36、ode+RO Data+RW Data)7586078(7408.28kB)红色的RW size就是我们要关注的,可以看到当前RW使用了3851K,而RAM的总数是4096K,所以还有充足的空间,heap增加个几十K没有什么问题。可以看到使用2和3都可以解决问题,通常把增大heap作为最后的手段。,.57,2023/7/7,MOCOR内存bug实例分析,内存覆盖:内存覆盖也是常见的一类内存问题,引起内存覆盖的原因很多,往往没有固定规律可循。而且有时出现覆盖后并不立刻死机,这样无法确认第一现场,增大了解决问题的难度。但在MOCOR平台下,我们有一个非常有用的工具:Bus Monitor。利用Bu

37、s Monitor(后文简称BM),我们有一个解决覆盖问题的一般性思路:首先确定被覆盖内存的地址(可能是一个地址范围),如果问题可以重现,且每次被覆盖的地址比较固定,则可以用BM监控被覆盖的地址,这样当内存被覆盖时会第一时间死机,可以迅速定位。Bus Monitor的用法比较简单,可以参考相关文档。,.58,2023/7/7,MOCOR内存bug实例分析,1.案例一 内存写入时越界是出现内存覆盖的一个常见原因,相对来说也比较好查的,只要找到越界的那块内存基本就可以定位,我们看下面的例子:客户项目发现进入电话本偶而会出现死机,死机现场:File:RTOSsourcesrccthreadx_mem

38、.cLine:364ASSERT(ASSERT:Error 0 x10(No memory,unable to allocate!),wdp_customer.c,line=2098,param=0 xFA4)初一看好像是个内存不足的,但实际不是,assert界面输入4后打出当前分配的内存,就会发现有错误:,.59,2023/7/7,MOCOR内存bug实例分析,.60,2023/7/7,MOCOR内存bug实例分析,可以看到最后一行“memory is corrupted”,表明在遍历mem header的链表时出错,这意味着某一块memory的header异常了,而且这块内存的地址是0 x

39、40bcc30。Assert界面输入3,dump出当前内存后,我们打开dump文件,找到0 x00bcc30这个地址:,.61,2023/7/7,MOCOR内存bug实例分析,.62,2023/7/7,MOCOR内存bug实例分析,0 x000bcc30之前的24个字节,就是该块内存的header,我们看到,next指针明显异常,说明至少next指针被覆盖了。然后再往前看,上一块内存的结束标志(END FLAG)也异常了,说明了上块内存的结束标志也被覆盖了。此外,我们再往前看,发现这两块被覆盖的内存的值,跟之前同样位置的值非常类似(都是0 x02xxxxxx)。综合以上的所有现象,我们可以认为

40、是上一块内存写越界造成内存覆盖的可能性非常大。因为0 x040bcc30是在app heap的范围,所以我们再来看app heap信息:,.63,2023/7/7,MOCOR内存bug实例分析,.64,2023/7/7,MOCOR内存bug实例分析,可以看到,红色部分0 x40bcc10开始的那一块内存,就是我们刚才确认了header被破坏的那一块内存。那么它上面的绿色那一行,就是写越界的那一块内存。这一块内存是在mmipb_wintab.c在11007行分配的。下面我们可以有两种方法:第一种是review 代码,找到越界的地方。因为内存分配的地方已经确定了,只要检查哪些地方会写这块内存,会不

41、会写越界就可以了。如果代码不复杂的话,会很快找到结果。第二种方法就是利用BM,可以用BM监控上一块内存的END FLAG地址,如果在该内存的生命期内,该地址的值被改写了,那么就会直接assert。这样可以直接定位越界的第一现场。,.65,2023/7/7,MOCOR内存bug实例分析,2.案例二:如果被覆盖的内存是静态内存,比如发现某些变量的值异常,可以在map里找到变量的地址,用BM来监控。某客户项目随机出现死机:File:RTOSsourcesrccthreadx_mem.cLine:494ASSERT(ASSERT:Error 0 x2(Invalid pool pointer!),ir

42、am_mgr.c,line=159,param=0 x8)Invalid pool pointer表明死机因为在pool上分配内存时,传入的pool结构异常。Assert后,pool的状态如下:,.66,2023/7/7,MOCOR内存bug实例分析,.67,2023/7/7,MOCOR内存bug实例分析,可以看到,pool的信息基本上都是乱的。我们前面提过,这里的数据都是从pool这个数组里读到的,所以问题很明显,这个数组肯定被覆盖了。下面又该BM出场了,因为pool属于静态变量,所以我们查找map文件,找到pool的首地址,在这个案例中是0 x04049e40。pool的第1项就是是16字节pool的控制块,从上图看16字节pool的名字都没打出来,估计是被覆盖了,所以我们用bus monitor监控 pool0.tx_block_pool_name 这个地址就可以了。,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号