UCOS-II内存管理
来源:互联网 发布:java swing的网格布局 编辑:程序博客网 时间:2024/05/16 06:54
内存管理:
我们知道,在 ANSI C 中可以用 malloc()和 free()两个函数动态地分配内存和释放内存。但是,在嵌入式实时操作系统中,多次这样做会把原来很大的一块连续内存区域,逐渐地分割成许多非常小而且彼此又不相邻的内存区域,也就是内存碎片。由于这些碎片的大量存在,使得程序到后来连非常小的内存也分配不到,我们讲到过用 malloc()函数来分配堆栈时,曾经讨论过内存碎片的问题。另外,由于内存管理算法的原因,malloc()和free()函数执行时间是不确定的。
在µC/OS-II 中,操作系统把连续的大块内存按分区来管理。每个分区中包含有整数个大小相同的内存块。利用这种机制,µC/OS-II 对 malloc()和 free()函数进行了改进,使得它们可以分配和释放固定大小的内存块。这样一来,malloc()和 free()函数的执行时间也是固定的了。
内存控制块:
为了便于内存的管理,在µC/OS-II 中使用内存控制块(memory control blocks)的数据结构来跟踪每一个内存分区,系统中的每个内存分区都有它自己的内存控制块。
typedef struct
{
//指向内存分区起始地址的指针 建立一个内存分区,OSMemCreate()时被初始化,在此之后就不能更改了。
void *OSMemAddr;
//指向下一个空闲内存控制块或者下一个空闲的内存块的指针
void *OSMemFreeList;
//内存分区中内存块的大小
INT32U OSMemBlkSize;
//内存分区中总的内存块数量
INT32U OSMemNBlks;
//内存分区中当前可以使用的空闲内存块的数量
INT32U OSMemNFree;
} OS_MEM;
在uC/OS-II中OS_MAX_MEM_PART(见文件 OS_CFG.H)定义了最大的内存分区数,该常数值至少应为 2。 每个内存分区必须含有至少两个内存块,每个内存块至少为一个指针的大小,因为同一分区中的所有空闲内存块是由指针串联起来的。
建立一个内存分区, OS_MEM *OSMemCreate ()
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U i;
if (nblks < 2)//在ucos中内存分区中内存块的大小最小为2
{
*err = OS_MEM_INVALID_BLKS;
return ((OS_MEM *)0);
}
if (blksize < sizeof(void *)) //每个内存块的大小至少为一个指针大小
{
*err = OS_MEM_INVALID_SIZE;
return ((OS_MEM *)0);
}
OS_ENTER_CRITICAL();
pmem = OSMemFreeList;
if (OSMemFreeList != (OS_MEM *)0)//在空闲的内存控制块中取得一个内存控制块
{
OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
}
OS_EXIT_CRITICAL();
if (pmem == (OS_MEM *)0)
{
*err = OS_MEM_INVALID_PART;
return ((OS_MEM *)0);
}
plink = (void **)addr;//指向内存分区的首地址
pblk = (INT8U *)addr + blksize;//指向内存分区中下一个内存块的首地址
for (i = 0; i < (nblks - 1); i++)//把内存分区中各个内存块链接成一个单向链表
{
*plink = (void *)pblk;//当前内存块的第一个元素存储下一个内存块的首地址
plink = (void **)pblk;//plink指向下一个内存块
pblk = pblk + blksize;//pblk指向下一个内存块
}
*plink = (void *)0;//最后一个内存块的第一个元素指向NULL
OS_ENTER_CRITICAL();
pmem->OSMemAddr = addr;
pmem->OSMemFreeList = addr;
pmem->OSMemNFree = nblks;
pmem->OSMemNBlks = nblks;
pmem->OSMemBlkSize = blksize;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (pmem);
}
分配一个内存块,OSMemGet()
void *OSMemGet (OS_MEM *pmem, INT8U *err)
{
void *pblk;
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree > 0)
{
pblk = pmem->OSMemFreeList;
pmem->OSMemFreeList = *(void **)pblk;
pmem->OSMemNFree--;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (pblk);
}
else
{
OS_EXIT_CRITICAL();
*err = OS_MEM_NO_FREE_BLKS;
return ((void *)0);
}
}
释放一个内存块,OSMemPut()
注意不要把和“当前分区中内存块大小不同”的内存块释放到当前分区。否则会引起灾难性后果。
INT8U OSMemPut (OS_MEM *pmem, void *pblk)
{
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree >= pmem->OSMemNBlks)
{
OS_EXIT_CRITICAL();
return (OS_MEM_FULL);
}
*(void **)pblk = pmem->OSMemFreeList;
pmem->OSMemFreeList = pblk;
pmem->OSMemNFree++;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
查询一个内存分区的状态,OSMemQuery()
在µC/OS-II 中,可以使用 OSMemQuery()函数来查询一个特定内存分区的有关消息。通过该函数可以知道特定内存分区中内存块的大小、可用内存块数和正在使用的内存块数等信息。所有这些信息都放在一个叫 OS_MEM_DATA 的数据结构中。
OS_MEM_DATA数据结构:
typedef struct
{
void *OSAddr; /* 指向内存分区首地址的指针 */
void *OSFreeList; /* 指向空闲内存块链表首地址的指针 */
INT32U OSBlkSize; /* 每个内存块所含的字节数 */
INT32U OSNBlks; /* 内存分区总的内存块数 */
INT32U OSNFree; /* 空闲内存块总数 */
INT32U OSNUsed; /* 正在使用的内存块总数 */
} OS_MEM_DATA;
我们知道,在 ANSI C 中可以用 malloc()和 free()两个函数动态地分配内存和释放内存。但是,在嵌入式实时操作系统中,多次这样做会把原来很大的一块连续内存区域,逐渐地分割成许多非常小而且彼此又不相邻的内存区域,也就是内存碎片。由于这些碎片的大量存在,使得程序到后来连非常小的内存也分配不到,我们讲到过用 malloc()函数来分配堆栈时,曾经讨论过内存碎片的问题。另外,由于内存管理算法的原因,malloc()和free()函数执行时间是不确定的。
在µC/OS-II 中,操作系统把连续的大块内存按分区来管理。每个分区中包含有整数个大小相同的内存块。利用这种机制,µC/OS-II 对 malloc()和 free()函数进行了改进,使得它们可以分配和释放固定大小的内存块。这样一来,malloc()和 free()函数的执行时间也是固定的了。
内存控制块:
为了便于内存的管理,在µC/OS-II 中使用内存控制块(memory control blocks)的数据结构来跟踪每一个内存分区,系统中的每个内存分区都有它自己的内存控制块。
typedef struct
{
//指向内存分区起始地址的指针 建立一个内存分区,OSMemCreate()时被初始化,在此之后就不能更改了。
void *OSMemAddr;
//指向下一个空闲内存控制块或者下一个空闲的内存块的指针
void *OSMemFreeList;
//内存分区中内存块的大小
INT32U OSMemBlkSize;
//内存分区中总的内存块数量
INT32U OSMemNBlks;
//内存分区中当前可以使用的空闲内存块的数量
INT32U OSMemNFree;
} OS_MEM;
在uC/OS-II中OS_MAX_MEM_PART(见文件 OS_CFG.H)定义了最大的内存分区数,该常数值至少应为 2。 每个内存分区必须含有至少两个内存块,每个内存块至少为一个指针的大小,因为同一分区中的所有空闲内存块是由指针串联起来的。
建立一个内存分区, OS_MEM *OSMemCreate ()
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U i;
if (nblks < 2)//在ucos中内存分区中内存块的大小最小为2
{
*err = OS_MEM_INVALID_BLKS;
return ((OS_MEM *)0);
}
if (blksize < sizeof(void *)) //每个内存块的大小至少为一个指针大小
{
*err = OS_MEM_INVALID_SIZE;
return ((OS_MEM *)0);
}
OS_ENTER_CRITICAL();
pmem = OSMemFreeList;
if (OSMemFreeList != (OS_MEM *)0)//在空闲的内存控制块中取得一个内存控制块
{
OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
}
OS_EXIT_CRITICAL();
if (pmem == (OS_MEM *)0)
{
*err = OS_MEM_INVALID_PART;
return ((OS_MEM *)0);
}
plink = (void **)addr;//指向内存分区的首地址
pblk = (INT8U *)addr + blksize;//指向内存分区中下一个内存块的首地址
for (i = 0; i < (nblks - 1); i++)//把内存分区中各个内存块链接成一个单向链表
{
*plink = (void *)pblk;//当前内存块的第一个元素存储下一个内存块的首地址
plink = (void **)pblk;//plink指向下一个内存块
pblk = pblk + blksize;//pblk指向下一个内存块
}
*plink = (void *)0;//最后一个内存块的第一个元素指向NULL
OS_ENTER_CRITICAL();
pmem->OSMemAddr = addr;
pmem->OSMemFreeList = addr;
pmem->OSMemNFree = nblks;
pmem->OSMemNBlks = nblks;
pmem->OSMemBlkSize = blksize;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (pmem);
}
分配一个内存块,OSMemGet()
void *OSMemGet (OS_MEM *pmem, INT8U *err)
{
void *pblk;
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree > 0)
{
pblk = pmem->OSMemFreeList;
pmem->OSMemFreeList = *(void **)pblk;
pmem->OSMemNFree--;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return (pblk);
}
else
{
OS_EXIT_CRITICAL();
*err = OS_MEM_NO_FREE_BLKS;
return ((void *)0);
}
}
释放一个内存块,OSMemPut()
注意不要把和“当前分区中内存块大小不同”的内存块释放到当前分区。否则会引起灾难性后果。
INT8U OSMemPut (OS_MEM *pmem, void *pblk)
{
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree >= pmem->OSMemNBlks)
{
OS_EXIT_CRITICAL();
return (OS_MEM_FULL);
}
*(void **)pblk = pmem->OSMemFreeList;
pmem->OSMemFreeList = pblk;
pmem->OSMemNFree++;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
查询一个内存分区的状态,OSMemQuery()
在µC/OS-II 中,可以使用 OSMemQuery()函数来查询一个特定内存分区的有关消息。通过该函数可以知道特定内存分区中内存块的大小、可用内存块数和正在使用的内存块数等信息。所有这些信息都放在一个叫 OS_MEM_DATA 的数据结构中。
OS_MEM_DATA数据结构:
typedef struct
{
void *OSAddr; /* 指向内存分区首地址的指针 */
void *OSFreeList; /* 指向空闲内存块链表首地址的指针 */
INT32U OSBlkSize; /* 每个内存块所含的字节数 */
INT32U OSNBlks; /* 内存分区总的内存块数 */
INT32U OSNFree; /* 空闲内存块总数 */
INT32U OSNUsed; /* 正在使用的内存块总数 */
} OS_MEM_DATA;
0 0
- uCos-II内存管理
- UCOS-II内存管理
- UCOS-II内存池管理
- ucos-ii示例7:内存管理测试
- UCOS-II的动态内存管理
- UCOS-II任务管理
- UCOS-II时间管理
- ucos II 内核学习之七:内存管理
- 用Buddy算法来改进uCos-ii内存管理方案
- ucos II 内核学习之七:内存管理
- 用Buddy算法来改进uCos-ii内存管理方案
- uCos的内存管理
- uCos的内存管理
- uCos的内存管理
- uCos的内存管理
- uCOS内存管理
- ucos内存管理
- uCos的内存管理
- python的文件内注释 help注释
- Filter过滤器
- Java创建型设计模式-建造者(3)
- 异常: -source 1.6 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符)
- Google Playe 服务搭建
- UCOS-II内存管理
- 拦截器---java
- 0-1背包问题
- java的FutureTask的public 方法的解析
- Java和Android的Thread源码分析
- Google浏览器 chrome老是拦截flash
- 模板_prim最小生成树算法
- lftp使用
- 本地文件跨域访问