Ucos源码分析
1.Ucos源码分析------任务控制块与任务调度
2.Ucos源码分析------事件控制块与事件控制
3.Ucos源码分析------信号量
4.Ucos源码分析------邮箱与队列
5.Ucos源码分析------事件标志组
6.Ucos源码分析------内存管理
7.Ucos源码分析------临界区与中断管理
8.Ucos源码分析------OS启动
9.Ucos总结
内存管理----OS_MEM.C
1.内存分区与内存块
应使用动态内存,要首先在内存中划分出可以进行动态分配的区域,这个划分出来区域叫做内存分区,每个分区要包含若干个内存块。μC/OS-II要求同一个分区中的内存块的字节数必须相等,而且每个分区与该分区的内存块的数据类型必须相同。
实现方式:定义一个二维数组
INT8U IntMenBuf[10][4]来存储INT8U类型的数据,10个内存块。每个内存块长度为4字节(8位)的数据。
内存控制块
控制块成员 | |
---|---|
OSMemAddr | 内存分区的指针 |
OSMemFreeList | 内存控制块链表指针 或 当前空闲的内存块指针 |
OSMemBlkSize | 分区内 内存块长度 |
OSMemNBlks | 分区内 内存块数目 |
OSMemNFree | 分区内 当前可分配的内存块数目 |
2.内存块的创建
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
参数:
addr 建立的内存区的起始地址。可以使用静态数组或在初始化时使用 malloc()函数建立。
Nblks 需要的内存块的数目。每一个内存区最少需要定义两个内存块。
Blksize 每个内存块的大小,最少应该能够容纳一个指针。
Err 是指向包含错误码的变量的指针。
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_MEM *pmem;
//内存块指向用
INT8U *pblk;
void **plink;
INT32U i;
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 memory blocks */
pblk = (INT8U *)addr + blksize;
//遍历内存块数目
for (i = 0; i < (nblks - 1); i++) {
//当前位置 的内容放下一个内存块的地址
*plink = (void *)pblk;
///plink指向 下一个内存块的地址
plink = (void **)pblk;
//pblk 获取下一内存块地址
pblk = pblk + blksize;
}
//最后一个内存块指向空
*plink = (void *)0; /* Last memory block points to NULL */
//内存控制块初始化
pmem->OSMemAddr = addr; /* Store start address of memory partition */
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 each memory blocks */
*err = OS_NO_ERR;
return (pmem);
}
3.内存块的获取
void *OSMemGet (OS_MEM *pmem, INT8U *err)
参数:
pmem 是指向内存区控制块的指针
Err 是指向包含错误码的变量的指针
void *OSMemGet (OS_MEM *pmem, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
void *pblk;
OS_ENTER_CRITICAL();
// 如果还有内存块
if (pmem->OSMemNFree > 0) { /* See if there are any free memory blocks */
//获取内存块的地址
pblk = pmem->OSMemFreeList; /* Yes, point to next free memory block */
//下一个内存块的地址 放在当前内存块的第一个位置[0]
pmem->OSMemFreeList = *(void **)pblk; /* Adjust pointer to new free list */
//内存块数目减少
pmem->OSMemNFree--; /* One less memory block in this partition */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR; /* No error */
return (pblk); /* Return memory block to caller */
}
OS_EXIT_CRITICAL();
*err = OS_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */
return ((void *)0); /* Return NULL pointer to caller */
}
4.内存块的释放
INT8U OSMemPut (OS_MEM *pmem, void *pblk)
参数:
pmem 是指向内存区控制块的指针
Pblk 是指向将被释放的内存块的指针
INT8U OSMemPut (OS_MEM *pmem, void *pblk)
{
//进入临界区的方式
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_ENTER_CRITICAL();
//判断内存块是不是满的
if (pmem->OSMemNFree >= pmem->OSMemNBlks) { /* Make sure all blocks not already returned */
OS_EXIT_CRITICAL();
return (OS_MEM_FULL);
}
// 将当前内存块的位置 放在新加入的内存块的第一个位置[0]
*(void **)pblk = pmem->OSMemFreeList; /* Insert released block into free block list */
//内存控制块的 当前内存块链表 指向新加入的内存块
pmem->OSMemFreeList = pblk;
//内存块数目+1
pmem->OSMemNFree++; /* One more memory block in this partition */
OS_EXIT_CRITICAL();
return (OS_NO_ERR); /* Notify caller that memory block was released */
}
经过多次OSMemPut()和OSMemGet()后,内存分区中内存块的指向,变的随意。