DEVICE_WRITES_ASYNCHRONOUSLY, SHARED_CACHE_LINES, SHARED_POINTERS ? 属性将指示cacheLib将怎样被使用
chapter 2 内存管理的实现
一、vxWorks操作系统内存管理的库函数
vxWorks提供了一个用于从内存池中动态分配、释放、重新分配内存块的工具。动态分配内存块可为任意大小;并且可自己指定内存池的尺寸。这些内存管理机制的基础是vxWorks能管理好几块单独的内存池。(注:内存池与内存分区为同一概念)这些工具主要是用库函数的形式提供。
MemPartLib库: 内核内存分区管理器
该库提供了一些用来管理内存块分配的内核工具,所分配的内存块是在某一特定内存分区分配;也就是说先分配好内存分区,再在分区中分配内存块。该库中包含2套内存分配例程:一套为memPart...( ),主要由创建和管理内存分区以及在某一个分区中分配和重新分配内存块的通用工具组成;另一套提供了与传统ANSI兼容的malloc()和free()接口,该接口主要用于系统内存分区中内存的分配和释放。
其中系统内存分区在内核初始化时被创建(内核在usrRoot()任务中,由kernelInit()函数初始化),系统内存分区的ID存储在全局变量memSysPartId中,该变量在memLib.h中被声明。
在分配内存时,一般情况下调用malloc()函数用于在系统分区中分配内存;而调用memPartAlloc()函数主要是用于在特定内存分区中分配内存。所有内存的分配均采用首先拟合调度算法(在下面的章节中将有详细的说明)。在用memPartFree()函数和free()函数释放内存时,先检查相邻的内存块是否为空闲,如果为空闲则合并成一大的空闲块。该库同时提供
memPartAlignedAlloc( )例程在特定的内存分区中来分配与某一规定边界对准的内存块(详细
情况可参见函数参数的说明)。
注意:不同体系结构有不同的对准限制,为了提供最优的性能,malloc()函数根据体系结构的不同返回一指向一个缓冲区的对准好的指针。缓冲区中可能有一部分空间不被使用。 以下为该库中函数的说明: 1.创建内存分区: PART_ID memPartCreate (
11
char * pPool, /* pointer to memory area */ unsigned poolSize /* size in bytes */ )
该例程用来创建包含在一指定内存池中的新内存分区。返回值为一分区ID,该ID可以被其它管理分区的例程使用(比如:在分区中分配内存块和释放内存块例程)。创建分区的目的主要是为了管理彼此分开的内存池。 2.将内存池中一内存块加到一内存分区 STATUS memPartAddToPool (
PART_ID partId, /* partition to initialize */ char * pPool, /* pointer to memory block */ unsigned poolSize /* block size in bytes */ )
3.从一内存分区中分配一块内存 void *memPartAlloc (
PART_ID partId, /* memory partition to allocate from */ unsigned nBytes /* number of bytes to allocate */ )
4.在一内存分区中释放一内存块 STATUS memPartFree (
PART_ID partId, /* memory partition to add block to */ char * pBlock /* pointer to block of memory to free */ )
5.将一内存块增加到系统内存分区 void memAddToPool (
char * pPool, /* pointer to memory block */ unsigned poolSize /* block size in bytes */ )
6.从系统内存分区中分配一块内存
12
void *malloc (
size_t nBytes /* number of bytes to allocate */ )
7.释放一块内存 void free (
void * ptr /* pointer to block of memory to free */ )
MemLib库 具有特色的内存管理器
该库为在内存分区中分配内存块提供了一些具有特色的工具。该库是memPartLib库的扩展,并且提供了一些增强的内存管理功能,包括:差错处理;对准分配;ANSI分配例程。 该库中包含3个与ANSI兼容的例程:calloc()为一数组分配一内存块;realloc()改变指定内存块的大小;cfree()释放由calloc申请的内存,将其归还到空闲的内存池中。
使用 memPartOptionsSet()和memOptionsSet()函数,可为每一分区选择多种调试选项。在分配和释放内存时,主要检测两种类型的错误:试图分配比可得的内存块更大的内存;在内存释放时,发现坏的内存块。在这两种情况下,错误状态将会返回。并且有4种错误处理选项可选。
MEM_ALLOC_ERROR_LOG_FLAG
在分配内存有错时,将一消息登记到日志中。
MEM_ALLOC_ERROR_SUSPEND_FLAG
在分配内存有错时,悬挂该任务。
MEM_BLOCK_ERROR_LOG_FLAG
在释放内存有错时,将一消息登记到日志中。
MEM_BLOCK_ERROR_SUSPEND_FLAG
在释放内存有错时,悬挂该任务。
1.为一内存分区设置调试选项 STATUS memPartOptionsSet (
PART_ID partId, /* partition to set option for */ unsigned options /* memory management options */ )
13
2.分配一对准内存
void *memalign (
unsigned alignment, /* boundary to align to (power of 2) */ unsigned size /* number of bytes to allocate */ )
3.在页的边界分配内存 void * valloc (
unsigned size /* number of bytes to allocate */ )
该例程保证所分配的缓冲区在页的边界。页的尺寸与体系结构相关。
4.在一特定的分区中重新分配一块内存 void *memPartRealloc (
PART_ID partId, /* partition ID */
char * pBlock, /* block to be reallocated */ unsigned nBytes /* new block size in bytes */ )。
5.找到最大可得的空闲内存块尺寸 int memPartFindMax (
PART_ID partId /* partition ID */ )
6.为系统内存分区设置调试参数 void memOptionsSet (
unsigned options /* options for system partition */ )
7.在系统内存分区中找到最大的空闲块
int memFindMax (void)
8.为一数组分配空间
14
void *calloc
(
size_t elemNum, /* number of elements */ size_t elemSize /* size of elements */ )
9.重新分配一块内存
void *realloc
(
void * pBlock, /* block to reallocate */ size_t newSize /* new block size */ )
10.释放一块内存
STATUS cfree
(
char * pBlock /* pointer to block of memory to free */
)
三、OSS中的内存管理
内存资源是系统重要的资源。为了节省和保护所需,根据实际情况将内存分为UB_SPAN,UB_SPAN*2,UB_SPAN*4,UB_SPAN*8 … UBPOOL_SIZE种大小,每种大小的内存用一队列来进行管理。并提供申请和归还的函数接口。
为满足软件的不同需求,UB是可定制的,参数如下: UBPOOL_SIZE 表示UB_POOL的数量 UB_SPAN 表示UB_POOL的粒度 MAX_UB_SIZE 表示最大的UB大小
内存队列是一个简单的循环队列,申请时从队列头取一空闲块,归还时归还队列尾。由于内存队列是系统的每个任务都会申请和归还的,设置了一个工作信号量来互斥。
每个内存块都有一个头,头中记录有该内存块的地址,该内存块所属于的内存队列,申请指针与归还指针。头的地址值能防止将非法的内存归还到队列中,头中记录的内存队列使归还时可以无需进行查找,即知道该内存块所属的队列,提高效率。申请指针是申请时填入的,归还指针是归还时填入的,两者配合起来可以查找内存的非法占用或长时间占用。
内存申请算法: 申请内存(VmGetUB)时,根据所需内存数值的移位,得到一级索引值,找到相应的UBPOOL
15