内存管理5个函数简介&用法 windows内存管理函数
◇ 内存控制块数据结构OS_MEM
◇ 内存分区建立函数OSMemCreate()
◇ 内存块分配函数OSMemGet()
◇ 内存块释放函数OSMemPut()
◇ 内存分区状态查询函数OSMemQuery()
◇ 内存控制块链表初始化函数OSMemInit()
他们一同构成内存管理模块来对需要管理的内存块进行简单的管理――分配(动态分配)和
释放(动态回收);
◇ 内存控制块数据结构OS_MEM
typedef struct {
void *OSMemAddr;
void *OSMemFreeList;
INT32U OSMemBlkSize;
INT32U OSMemNBlks;
INT32U OSMemNFree;
} OS_MEM;
系统中每个内存分区必须有一个属于自己的内存控制块,只有这样,内存管理模块中的五个
函数才能对这个内存分区进行管理和操作;
操作系统首先在内存中声明了一个全局的内存控制块数组和指针:
static OS_MEM *OSMemFreeList;
static OS_MEM OSMemTbl[OS_MAX_MEM_PART];
然后在系统初始化的时候调用内存控制块链表初始化函数把这个全局的内存控制块数组
OSMemTbl[ ]构建成一个单向链表,并把这个链表的头指针赋给OSMemFreeList,这样以后,
每当用内存分区建立函数OSMemCreate()建立一个分区时,从这个链表中取出一个内存控
制块来对这个内存分区进行管理;内存控制块数组的大小决定系统中内存分区的最大数
目;
◇ 内存分区建立函数OSMemCreate()
要建立一个内存分区,必须具备三个条件:
1. 有供建立内存分区的内存空间:一般处理方法是以二维数组的形式来声明一个变量,这
个变量在编译、链接的时候必定分配给一定的内存空间,这个内存空间只能通过内存块分配
函数来获取使用;
2. 内存控制块数组中有闲置的内存控制块:一般的处理方法是先统计需要建立的内存分区
的数目,然后依此来声明足够的内存控制块;
3. 声明一个内存控制块指针,便于以后对这个内存分区的访问;
内存分区建立后,这个二维数组就被构建成了一个单向链表,每个节点就是一个内存块,它
由两部分组成:指向下一个内存块的指针(不能用来作为动态内存来使用)、能够作为动态
内存来使用的存储空间;
◇ 内存块分配函数OSMemGet()
用户创建的任务要使用内存分区中的内存块,就必须通过调用内存分配函数来申请;一般的
处理方法是:先在用户任务中声明一个void类型的指针和一个INTU8 型变量,然后调用
OSMemGet()来从指定的内存分区中申请一个内存块,并把内存块的指针赋给预先声明的
void类型指针;接着对INTU8 型变量进行判断,看申请内存块是否成功。如果成功,就可以
使用这个内存块中可以用动态使用的存储空间。
◇ 内存块释放函数OSMemPut()
用户创建的任务不在使用申请来的内存块的时候,必须及时的调用OSMemPut()来把内存块
释放到相应的内存分区中去。需要注意的是,这个内存块从那个内存分区中申请来的就必须
释放到那个内存分区中去,否则会造成系统崩溃;这个用户在编写任务的时候注意就可以避
免了;
OSMemGet()和OSMemPut()应该成对使用;
◇ 内存分区状态查询函数OSMemQuery()
调用内存分区状态查询函数可以获取一个内存分区的相关信息,它的实现方法就是把内存分
区控制块中的信息拷贝到OS_MEM_DATA的数据结构体中供调用查看、使用;那么大家也许会
问为什么我们不直接通过访问分区控制块来获取这个分区的使用信息呢?这就涉及到代码的
临界区的问题。试想如果我们直接访问内存控制块中的域的话而没有关中断的话,那么如果
时钟节拍到来的时候我们的访问肯定被打断(我们只获取了内存分区的部分信息,还有部分
信息没来得及获取),这个时候通过调度准备就绪而且优先级高的任务得以运行,那么前面
的任务就得等待;试想现在运行的任务如果对这个内存分区进行操作的话,那么上一个任务
获取的内存分区的信息就不一致了,这个可能给我们不可预测的后果;为此在访问内存分区
控制块前,我们得关中断,之后我们还得开中断,这个给我们的移值带来琐碎的麻烦!这也
就是编写这个函数的原因!
下面就内存管理模块来举个例子:
#define BlockNum 100
#define BlockSize 32
OS_MEM *CommRAMA_Ptr;
OS_MEM *CommRAMB_Ptr;
INT8U CommRAMA[BlockNum][BlockSize];
INT8U CommRAMB[BlockNum][BlockSize*4];
… … … …
void main(void)
{
INT8U error;
… … … …
CommRAMA_Ptr=OSMemCreate(CommRAMA,BlockNum, BlockSize,error);
CommRAMB_Ptr=OSMemCreate(CommRAMB,BlockNum,BlockSize*2,error);
… … … …
OSStart();
}
void MyTask(void)
{
… … … …
INT8U Error;
OS_MEM_DATA MemInfo;
INT8U BlkA_Ptr,BlkB_Ptr;
… … … …
for(){
Error= OSMemQuery(CommRAMA_Ptr,&MemInfo);------(1)
If(MemInfo.OSNFree≥2){ ------(2)
BlkA_Ptr=(INT8U *)OSMemGet(CommRAMA_Ptr,&Error);------(3)
BlkB_Ptr=(INT8U *)OSMemGet(CommRAMA_Ptr,&Error);------(4)
… … … …
OSMemPut(CommRAMA_Ptr,BlkA_Ptr);
OSMemPut(CommRAMA_Ptr,BlkB_Ptr);
}else{
Error= OSMemQuery(CommRAMB_Ptr,&MemInfo);
If(MemInfo.OSNFree≥1){
BlkA_Ptr=(INT8U*)OSMemGet(CommRAMB_Ptr,&Error);---(5)
… … … …
OSMemPut(CommRAMA_Ptr,BlkB_Ptr);
}else{
OSTimeDly(1);
}
}
… … … …
}
}
系统建立了两个内存分区:内存分区CommRAMA的内存块的大小为32个INT8U(可用的为31个
INT8U),内存分区CommRAMB的内存块的大小为128个INT8U(可用的为127个INT8U);现在
用户创建了一个名为MyTask的任务,它运行时需要一个大小为60个INT8U的内存空间,在这
个系统有两个解决办法:从内存分区CommRAMA中申请两个内存块以及从内存分区CommRAMB中
申请一个内存块;具体的实现方法是先获取内存分区CommRAMA的使用信息,看有没有足够的
内存块(剩余块数不小于2)如果够的话,就不用从内存分区CommRAMB中申请了,否则就的
从CommRAMB中申请,如果这里也没有的话,那么就等待一个时钟节拍!
使用内存管理模块需要做的工作还有:
1.打开配置文件OS_CFG.H,将开关量OS_MEM_EN设置为1:
#define OS_MEM_EN 0
2.打开配置文件OS_CFG.H,设置系统要建立的任务分区的数量:
#define OS_MAX_MEM_PART 2
更多阅读
去痘印最有效的方法,5个去痘印个偏方 最有效去痘印方法
去痘印最有效的方法,5个去痘印个偏方——简介通常抗痘的战争后,都会留下痕迹——痘印,就像是勇敢的战士们上战场回来后会留下光荣的伤疤。可是痘印的存在却是让女生们都无法直视自己的脸,那么如何消灭脸上的痘印呢?让小编教你几个有效的
做好手机短信营销的5个技巧 手机精准营销短信平台
做好手机短信营销的5个技巧——简介在手机高度普及的商场,手机短信群发已经成为销售员开展业务的主要武器,已经有许多企业利用手机短信做广告,销售员利用手机短信问候客户联络感情,我今天要谈的是如何利用手机短信做好电话营销?做好手机
与陌生女孩搭讪的5个技巧 女孩遇到陌生人搭讪
与陌生女孩搭讪的5个技巧——简介生活中,总会这样的情景,我们在城市的角落里遇到至少是外貌上让自己心动的女孩。是怅然若失的擦肩而过,还是勇敢的走上前去,相信是很多男人都遇到过的问题。上或不上?上了该说什么?说了她会不会不理我?在你
呼啦圈能瘦腰吗?详解呼啦圈瘦腰的5个要点 呼啦圈能瘦腰吗
呼啦圈能瘦腰吗?详解呼啦圈瘦腰的5个要点——简介 呼啦圈是不少美眉喜爱的瘦腰工具,因为它是延长运动时间而且是持续性的运动,当进入有氧运动的阶段的时候,可以充分锻炼腰腹部的脂肪和肌肉,达到瘦腰的效果。加上转呼啦圈可以帮助肠道的
5个月宝宝拉肚子怎么办 宝宝拉肚子的处理方法
5个月宝宝拉肚子怎么办——简介 对于正处于发育关键期的宝宝来说,腹泻不但直接影响他们对营养物质的吸收,假若护理不当导致病情加重,甚至可能危及生命!新生宝宝腹泻,究其原因可分为肠道内感染、肠道外感染和非感染性腹泻三大类。要找出