μC/OS-III_存储管理


        在嵌入式操作系统中,多次使用malloc()和free()会将原来很大的一块连续存储区域,逐渐地分成许多非常小且彼此不相邻的存储区域,这就是存储碎片。由于存储碎片数量的不断增加,程序到后来可能无法分得一块连续的存储区域。另外,由于存储空间管理算法的原因,要得到一块连续的存储块,且大小足以满足malloc()函数的要求,malloc()和free()函数要执行的时间也是不确定的。

        μC/OS-III提供了一种替代malloc()和free()函数的方法,将连续的大块存储空间进行分区管理,每个分区中包含整数个大小相同的存储块,由μC/OS-III管理。通过该种机制,使应用程序可以获得固定大小的存储块。由此,分配和释放存储块花费的时间是常数,是固定可知的。


存储分区相关API
函数含义
OSMemCreate()创建一个存储分区
OSMemGet()从存储分区中获得一个存储块
OSMemPut()将一个存储块归还到存储分区中

1 创建存储分区

        在使用存储分区之前,必须首先创建存储分区,并告知μC/OS-III一些存储分区的基本信息以便其管理存储空间。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200710091739170.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dST1dfMTc=,size_16,color_FFFFFF,t_70#pic_center) (1)当创建存储分区时,应用代码提供存储分区控制块OS_MEM的地址,一般情况下,**存储分区控制块从静态存储空间中分配**,但也可以通过malloc()动态分配。 (2)OSMemCreate()函数将需要管理的连续存储空间整理成单向链表,并将指针保存到OS_MEM结构体的开头。 (3)每个存储块的容量不得小于保存一个指针变量所需的空间,根据链表的要求,每个块中需要有指向下一块的指针。
/*静态分配存储控制空间*/
OS_MEM	MyPartition;										/*应用程序为存储分区控制块分配空间*/
/*应用程序需要为被分成存储空间块的存储分区分配空间
可以通过静态分配也可以通过动态malloc()函数分配
但是该存储空间只能分配不能释放,其他任务的生存可能依赖该存储空间*/
CPU_INT08U	MyPartitionStorage[12][100];					

void main(void)													/*创建存储分区的最佳时机之一是在main函数中,开始多任务之前*/
{
	OS_ERR	err;
	...
	OSInit(&err);
	/*Check error*/
	OSMemCreate((OS_MEM*)		&MyPatition,					/*将存储分区控制块的地址传入,用户不能引用OS_MEM数据结构的内部成员*/
				(CPU_CHAR*)		"My Partition",					/*为存储分区控制块指定一个ASCII字符串别名*/
				(void*)			&MyPartitionStorage[0][0],		/*要分配的存储空间的基地址*/
				(OS_MEM_QTY)	12,								/*设定存储空间有多少个存储块可用*/
				(OS_MEM_SIZE)	100,							/*设定存储空间中每个存储块的大小*/
				(OS_ERR*)		&err);							/*错误返回码*/
	/*Check error*/
	...
	OSStart(&err);
	/*Check error*/
}

/*动态分配存储控制空间*/
OS_MEM*	MyPartitionPtr;					/*动态分配存储控制块基地址*/
...
void main(void)
{
	OS_ERR	err;
	void*	P_Stroage;					/*动态分配的存储空间基地址*/
	...
	OSInit(&err);
	/*Check error*/
	MyPartitionPtr = (OS_MEM*)malloc(sizeof(OS_MEM));
	if(MyPartitionPtr != (OS_MEM*)0)
	{
		P_Stroage = malloc(sizeof(CPU_INT08U)*12*100);		/*动态分配12*100个CPU_INT08U个存储空间*/
		if(P_Stroage != (void*)0)
		{
			OSMemCreate((OS_MEM*)		MyPartitionPtr,		/*将存储分区控制块的地址传入,用户不能引用OS_MEM数据结构的内部成员*/
						(CPU_CHAR*)		"My Partition",		/*为存储分区控制块指定一个ASCII字符串别名*/
						(void*)			P_Stroage,			/*要分配的存储空间的基地址*/
						(OS_MEM_QTY)	12,					/*设定存储空间有多少个存储块可用*/
						(OS_MEM_SIZE)	100,				/*设定存储空间中每个存储块的大小*/
						(OS_ERR*)		&err);				/*错误返回码*/
			/*Check error*/
		}
	}
}

2 从分区中获取存储块

OS_MEM	MyPartition;							/*存储分区控制块应该能被使用该分区的任务和ISR读/写*/
CPU_INT08U* MyDataBlkPtr;						/*获得分区块的前提是,用户应该知道分区块的大小,以防止数据溢出*/

void MyTask(void* p_arg)
{
	OS_ERR	err;
	...
	while(DEF_ON)
	{
		...
		MyDataBlkPtr = (CPU_INT08U*)OSMemGet(OS_MEM*)&MyPartition, (OS_ERR*)&err);
		if(err == OS_ERR_NONE)		/*通过检查错误码 判断是否有空闲块分为当前任务*/
			/*存储分区分出一个块,并将这个块的基地址赋给了MyDataBlkPtr*/
		...
	}
}

3 将存储块归还到分区中

OS_MEM	MyPartiton;
CPU_INT08U*	MyDataBlkPtr;

void MyTask(void* p_arg)
{
	OS_ERR	err;
	...
	while(DEF_ON)
	{
		...
		/*当有多个存储分区时,要对存储块属于哪个存储分区进行检查*/
		OSSemPut((OS_MEM*)MyPartiton, (void*)MyDataBlkPtr, (OS_ERR*)&err);
		if(err == OS_ERR_NONE)
			/*存储块归还成功*/
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值