微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > UC/OS-II的内存管理OSMemCreate()分析

UC/OS-II的内存管理OSMemCreate()分析

时间:12-01 来源:互联网 点击:
我们在写应用程序的过程中通常都是采用一个malloc/free系列函数进行内存的管理,这样分配的内存空间是从应用程序的栈空间分配处理,一般而言我们在写程序的过程中要对内存空间进行适时的释放,才不至于导致栈空间的不足,当然这样也会导致内存垃圾的产生,因为不同大小的内存分配因为对齐等原因导致很多的内存不能再使用,进而使得系统的可用内存越来越小,因此在实时操作系统中通常都需要创建自己的内存管理操作。

uc/os-II中的内存管理主要是采用内存分区控制块实现的,具体的实现过程如下:

/*
关于内存控制块的结构体,
用来跟踪每一个内存分区
每一个分区可以分成很多个小的内存块
每一个内存块的大小都是相同的
*/
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
typedef struct { /* MEMORY CONTROL BLOCK */
/*内存的起始地址*/
void *OSMemAddr; /* Pointer to beginning ofmemorypartition */
/*
链表指针,
能够快速的实现内存的控制
*/
void *OSMemFreeList; /* Pointer to list of free memory blocks */
/*每一个内存块的大小*/
INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory */
/*存在的内存块数量*/
INT32U OSMemNBlks; /* Total number of blocks in this partition */
/*空闲的内存空间*/
INT32U OSMemNFree; /* Number ofmemoryblocks remaining in this partition */
} OS_MEM;

基本的实现思想就是将内存分区分解成很多的大小相同的内存块,然后OSMemFreeList将所有的内存块链接起来,但是此处的链接与我们常用的链表存在一定的差别,这也是内存管理中常用的技巧之一,即在当前块的起始地址处存放下一个内存块的地址,这样就能比较快速的实现内存的管理。在uc/os-II的内存管理代码的OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)函数中存在一些代码难点。特别是强制类型转换的使用,在uc/os-II中我们看见了大量的强制类型转换问题,下面就做一下简要的分析:

OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatusregister */
OS_CPU_SR cpu_sr;
#endif
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U i;

/*检测参数的正确性*/
#if OS_ARG_CHK_EN > 0
if (addr == (void *)0) { /* Must pass a valid address for the memory part. */
*err = OS_MEM_INVALID_ADDR;
return ((OS_MEM *)0);
}
if (nblks < 2) { /* Must have at least 2 blocks per partition */
*err = OS_MEM_INVALID_BLKS;
return ((OS_MEM *)0);
}
if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer */
*err = OS_MEM_INVALID_SIZE;
return ((OS_MEM *)0);
}
#endif

OS_ENTER_CRITICAL();
/*得到空闲的内存控制块*/
pmem = OSMemFreeList; /* Get next free memory partition */
/*更新内存控制块链表*/
if (OSMemFreeList != (OS_MEM *)0) { /* See if pool of free partitions was empty */
OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
}
OS_EXIT_CRITICAL();
if (pmem == (OS_MEM *)0) { /* See if we have a memory partition */
*err = OS_MEM_INVALID_PART;
return ((OS_MEM *)0);
}
/*
将一个分区的各个内存小块链接起来,
形成一个链表
*/
plink = (void **)addr; /* Create linked list of free memoryblocks */
/*得到一个固定的*/
pblk = (INT8U *)addr + blksize;
for (i = 0; i < (nblks - 1); i++) {
/*在当前的地址处保存下一个内存块的地址*/
*plink = (void *)pblk;
/*将指针指向下一个内存块*/
plink = (void **)pblk;
/*得到第三个内存块的地址*/
pblk = pblk + blksize;
}
/*
将最后一个内存块的下一个地址设置为NULL;
*/
*plink = (void *)0; /* Last memoryblockpoints to NULL */
/*得到内存分区的起始地址*/
pmem->OSMemAddr = addr; /* Store start address ofmemorypartition */
/*
将内存块的链表头指向当前地址
通过链表能够快速的找到下一个内存块的地址
只需要对链表取地址,
然后将指针指向该地址就能实现快速的切换
*/
pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks */
/*空闲的内存块*/
pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB */
/*内存的总块数*/
pmem->OSMemNBlks = nblks;
/*内存块的大小*/
pmem->OSMemBlkSize = blksize; /* Store block size of eachmemoryblocks */
*err = OS_NO_ERR;
return (pmem);
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top