基于VxWorks的内存管理和一个内存泄漏查找实例
本文主要分三部分,第一章介绍基于VxWorks的内存管理的主要内容,第二章介绍应用在ZXWR NB01产品软件设计中OSS的内存管理方法,第三章介绍实际应用中一个内存泄漏查找的实例。
Chapter 1 基于VxWorks的内存管理
一、综述
对于一个采用了VxWorks操作系统的主处理器构成的系统,主内存的管理机制主要由BSP来实现,包括内存的初始化和内存的访问接口;
主内存的初始化由romInit()实现,总线访问(对设备而言)在sysHwInit()中初始化; BSP对内存访问的支持和管理策略: ? 主内存的配置 ? 对MMU的虚拟映射 ? Cache策略 ? 内存探针
BSP的硬件寄存器在sysHwInit中初始化,通常的设备(串口除外)寄存器当设备初始化时被初始化;
为调示方便,在BSP开发期间禁止cache和MMU直到以下的情况实现: ? 内核被成功的激活 ? 驱动器经过测试 二、内存配置
BSP负责配置主内存来实现快速的内核操作 ? 一些关键地址必须被定义 ? 如果使用MMU,必须定义内存映射 ? 提供支撑程序
内存地址的定义在以下的文件中: -----config.h-用户可配置的
-----
BSP提供的内存函数:sysMemTop()、sysNvRamSet()、sysNvRamGet()
1
上图代表了下载的镜像被重定位后的RAM的分区;一个WDB代理内存池仅仅当与VxWorks镜像一起的Tornado工具被使用时才需要;用户保留内存是不被VxWorks的程序所访问的。
char * sysMemTop(void)
? 函数返回系统内存的首地址,代码在sysLib.c中;
? 宏USER_RESERVED_MEM定义了不被VxWorks程序访问的用户保留内存的大小
? 如果BSP不支持可选函数sysPhyMemTop(),由LOCAL_MEM_LOCAL_ADRS+ LOCAL_MEM_SIZE
替代。
? 内存的自动分区允许在初始化时配置物理内存的大小,如果自动分区功能没有激活,物理
内存的大小由config.h中的LOCAL_MEM_SIZE静态定义;
2
? 自动分区的具体细节是根据系统的不同而异的,典型的有:
当DRAM在romInit()中被初始化时,配置信息存储在内存的控制寄存器或/和软件结构中; 在分区时,配置信息被读取来计算所有物理内存的大小。
? 支持自动分区的函数是sysPhysMemTop():char * sysPhysMemTop(void)
函数返回的是物理内存的首地址;
如果LOCAL_MEM_AUTOSIZE在config.h中被定义,该函数可提供动态的内存分区; BSP对自动分区的支持是可选的,如果参考BSP的代码没有静态的修改,被定义的缺省值将被返回;
SysPhysMenTop()是由sysHwInit()函数调用的:该函数必须在KernelInit()之前,也就是sysMemTop被调用时。内核激活的调用:
? 所有的BSPs必须有NVRAM接口即使在目标环境中没有非易失RAM,接口必须支持:
sysNvRamSet() 、sysNVRamGet()
? 所有NVRAM的大小必须在config.h中定义为NV_RAM_SIZE的大小,如果没有NVRAM则定义
为NONE;
? 如果提供了,NVRAM用于存储可下载的镜像的启动参数;
? 缺省配置在NVRAM的开头保留了255个字节用于启动参数的存储;
? 缺省的启动参数在config.h中定义并静态连接到可下载的VxWorks的镜像中,缺省条件下
是没有NVRAM的;
? NVRAM为启动参数分配的大小和定位在configAll.h中定义:
BOOT_LINE_SIZE定义NVRAM为启动参数保留的大小,缺省为255字节;
NV_BOOT_OFFSET定义了启动参数在NVRAM中的首地址,缺省为0; 为覆盖缺省值,在config.h中重定义宏。
? set/get NVRAM的程序
部分驱动器在../src/drv/mem目录下,如果没有NVRAM使用../src/drv/mem/下的
3
nullNvRam.c,该程序包含在sysLib.c中。
? NVRAM支持的函数:
STATUS sysNvRamSet(string,strLen,offset) STATUS sysNvRamGet(string,strLen,offset)
三、MMU机制
? MMU主要是受系统库的控制,BSP则负责提供对物理内存描述符的支持:
由MMU使用的物理内存描述符用来创建与虚拟地址空间的初始映射; 缺省的映射是平滑的,一对一的在物理和虚拟内存空间的映射。
? MMU由tUsrRoot任务调用usrMmuInit()进行初始化和使能
首先初始化系统内存池的设置; 其次是MMU的初始化;
? MMU的支持可提供基本级别或通过可选产品VxVMI两种,本章主要讨论基本级:对基本的
MMU支持,宏INCLUDE_MMU_BASIC必须在config.h中被定义; ? UsrMmuInit() 的代码在../src/config/usrMmuInit.c中
? 初始的(静态的)物理内存映射定义在sysLib.c中,是定义在../h/vmLib.h中一个结构
数组SYS_PHYS_MEM_DESC:
? 映射的状态有:有效或无效、可写或不可写、可高速缓存或不可高速缓存 ? 虚拟-物理的映射举例:
4
? 由结构库使用的配置宏用于初始化MMU的转换表; ? 配置宏在../h/vmLib.h中定义
? 修改物理-虚拟内存的映射:修改sysPhysMemDesc[](静态映射),调用
vmBaseStateSet()(动态修改);
? 映射到一个页面的内存:页面的大小由宏VM_PAGE_SIZE在configAll.h中定义的,缺省为
8k(对PowerPC结构是4K),对sysPhysMemDesc[]映射的长度应该是页面大小的整数倍; ? 每一张表的入口都需要一个物理内存的页表入口:为能定义多少地址映射设置一个上限; ? 一些MMU也应该限制有多少内存能被映射,参考硬件的文档。
? 虚拟内存映射必须映射所有的可被访问的物理内存,包括被映射的设备内存
(Ethernet,SCSI, etc);
? 当MMU使能时,对非虚拟-物理映射的地址进行写操作时会导致总线错误; ? 通常虚拟-物理映射的配置有:
Local RAM-有效、可写、可高速缓存 ROM-有效、只读、经常高速缓存 Flash-有效、可写、非高速缓存 I/O设备-有效、可写、非高速缓存
脱离目标板的内存-有效、可写、非高速缓存
? 可编程Flash需要直接访问因此不能被高速缓存,但如果flash是只读的就可以被高速缓
5