《LINUX实操:SylixOS 定长内存管理》要点: 本文介绍了LINUX实操:SylixOS 定长内存管理,希望对您有用。如果有疑问,可以联系我们。
所谓定长内存,指的是用户每次分配获得的内存年夜小是相同的,即使用的是有确定长度的内存块.同时,这些内存块总的个数也是确定的,即整个内存总的年夜小也是确定的.这和通常理解的内存池的概念是一样的.
使用定长内存管理的内存,有两大长处:一是由于事先已经分配好了足够的内存,可极大提高关键应用的稳定性;二是对于定长内存的管理通常有更为简单的算法,分配/释放的效率更高.在 SylixOS 中,将管理的一个定长内存称作 PARTITION,即内存分区.
2. 定长内存管理设置
SylixOS可以通过API操作实现定长内存管理功效.
2.1? ? ? 创立内存分区
#include<SylixOS.h>
LW_OBJECT_HANDLE? Lw_Partition_Create(CPCHAR? ? ? ? ? ? pcName,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PVOID? ? ? ? ? ? ? pvLowAddr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ULONG? ? ? ? ? ? ? ulBlockCounter,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? size_t? ? ? ? ? ? stBlockByteSize,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ULONG? ? ? ? ? ? ? ulOption,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LW_OBJECT_ID? ? ? *pulId)
|
函数Lw_Partition_Create 原型阐发:
1.此函数成功时返回一个内存分区句柄,失败时返回LW_HANDLE_INVALID并设置差错号;
2.参数pcName指定该内存分区的名称,可以为LW_NULL(最年夜字长为32字节);
3.参数pvLowAddr为用户定义的一片内存的低地址,即起始地址.该地址必需满足一个CPU字长的对齐,如在32位系统中,该地址必需4字节对齐;
4.参数 ulBlockCounter 为该内存分区的定长内存块数目;
5.参数 stBlockByteSize 为内存块的大小,必需不小于一个指针的长度,在32位系统中为4字节;
6.参数ulOption为创立内存分区的选项,如表 2-1所示.
表 2-1? 内存分区创立选项
7.输出参数 pulId 保留该内存分区的 ID,与返回值相同.可以为 LW_NULL.
?
注:驱动程序或内核模块才能使用LW_OPTION_OBJECT_GLOBAL 选项,对应的LW_OPTION_OBJECT_LOCAL 选项用于应用程序.为了使应用程序有更好的兼容性,建议使用LW_OPTION_DEFAULT选项,该选项包括了 LW_OPTION_OBJECT_LOCAL 的属性.
SylixOS的Lw_Partition_Create把已分配好的一块大内存(pvLowAddr)通过一个PARTITION控制块进行管理,PARTITION控制块内容如法式清单 2-1所示.
法式清单2-1? PARTITION控制块
/淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱*
? PARTITION 节制块
淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱淫乱*/
typedefstruct {
? ? LW_LIST_MONO? ? ? ? PARTITION_monoResrcList;? ? ? ? ?/*? 余暇资源表? ? ? ? ? ? ?*/
? ? UINT8? ? ? ? ? ? ? ? PARTITION_ucType;? ? ? ? ? ? ? ? /*? 类型标记? ? ? ? ? ? ? ?*/
? ? PLW_LIST_MONO? ? ? ? PARTITION_pmonoFreeBlockList;? /*? 余暇内存块表? ? ? ? ? ?*/
? ? size_t? ? ? ? ? ? ? PARTITION_stBlockByteSize;? ? ? /*? 每一块的年夜小? ? ? ? ? ?*/
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*? 必需大于 sizeof(PVOID)*/
? ? ULONG? ? ? ? ? ? ? ? PARTITION_ulBlockCounter;? ? ? ? /*? 块数目 ? ? ? ? ? ? ? ? */
? ? ULONG? ? ? ? ? ? ? ? PARTITION_ulFreeBlockCounter;? ? /*? 余暇块数量? ? ? ? ? ? ?*/
? ? UINT16? ? ? ? ? ? ? PARTITION_usIndex;? ? ? ? ? ? ? ? /*? 缓冲区索引? ? ? ? ? ? */?
? ? CHAR? ? ? ? ? ? ? ? PARTITION_cPatitionName[LW_CFG_OBJECT_NAME_SIZE];
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*? 名字? ? ? ? ? ? ? ? ? */
? ? LW_SPINLOCK_DEFINE? (PARTITION_slLock);? ? ? ? ? ? ?/*? 自旋锁? ? ? ? ? ? ? ? */
} LW_CLASS_PARTITION;
|
Lw_Partition_Create对特定内存管理好后,会返回一个LW_OBJECT_HANDLE句柄.之后用户必要对这块内存进行获取、释放和删除等,都可以通过这个句柄进行操作.
2.2? ? ? 获取/返还内存块
PVOID? Lw_Partition_Get (LW_OBJECT_HANDLE? ulId)
PVOID? Lw_Partition_Put (LW_OBJECT_HANDLE? ulId,PVOID? pvBlock)
|
调用 Lw_Partition_Get 函数可以获得一个内存分区的内存块,其大小为创立内存分区时指定的大小,调用Lw_Partition_Put 函数将获得的内存块(Lw_Partition_Get 函数获得)返回给内存分区.
注:如果pvBlock为 NULL,则设置差错号为 ERROR_PARTITION_NULL.
2.3? ? ? 删除内存分区
ULONG? Lw_Partition_Delete (LW_OBJECT_HANDLE? *pulId)
ULONG? Lw_Partition_DeleteEx (LW_OBJECT_HANDLE? *pulId,BOOL? bForce)
|
如果一个内存分区中有内存块还在被使用,则理论上不该该立刻被删除.如果bForce为 LW_TRUE,则 Lw_Partition_DeleteEx 忽略该条件直接删除该分区.通常情况下应用程序不该该使用该方式,这可能会导致内存错误.建议一般情况下使用 Lw_Partition_Delete 函数,它相当于下面调用,这样避免释放还在使用的内存.
Lw_Partition_DeleteEx(pulId,LW_FALSE);
|
3. 定长内存管理使用
好比程序需要创建一个链表,可以使用定长内存管理.如程序清单 3-1所示.
法式清单 3-1? 法式代码
#include<stdio.h>
#include<SylixOS.h>
?
typedefstruct my_element {
? ? INTiValue;
} MY_ELEMENET;
?
#define? ?ELEMENT_MAX (8)
?
/*
?* 即当_G_pucMyElementPool 的地址不满足布局体 MY_ELEMENT 的对齐需求时,在有些硬件上,
?* 拜访成员变量 iValue 将产生多字节不对齐拜访的错误(典型的硬件平台如 ARM).
* 应该将_G_pucMyElementPool 的类型定义为UINT8,即单字节拜访,逻辑上它的起始地址可以是任? * 何对齐值.
?*/
MY_ELEMENET_G_pmyelement[ELEMENT_MAX];
LW_STACK? ? _G_pucMyElementPool[sizeof(MY_ELEMENET) * ELEMENT_MAX /
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sizeof(LW_STACK)]; ? ? ? ?/*? 申请一段内存空间? ? */
LW_HANDLE? ?_G_hMyPartition;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*? 内存治理句柄 ? ? ? ? */? ? ? ? ? ? ? ? ? ? ? ? ?
?
intmain(intargc,char *argv[])
{
? ? MY_ELEMENET *peleTable[ELEMENT_MAX] ? = { LW_NULL };
? ? MY_ELEMENET *peleTmp? ? ? ? ? ? ? ? ? = NULL;
? ? ULONG? ? ? ? ulError;
? ? INT? ? ? ? ? i? ? ? ? ? ? ? ? ? ? ? ?= 0;
?
? ? _G_hMyPartition = Lw_Partition_Create("my_partition",_G_pucMyElementPool,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ELEMENT_MAX,sizeof(MY_ELEMENET),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LW_OPTION_DEFAULT,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LW_NULL);
? ? if (_G_hMyPartition == LW_HANDLE_INVALID) {
? ? ? ? fprintf(stderr,"create partition failed.n");
? ? ? ? return (-1);
? ? }
? ? /*
? ? ?* 最多能够得到多少个元素内存
? ? ?*/
? ? while (1) {
? ? ? ? peleTmp = (MY_ELEMENET *) Lw_Partition_Get(_G_hMyPartition);
? ? ? ? if (peleTmp != LW_NULL) {
? ? ? ? ? ? peleTable[i] = peleTmp;
? ? ? ? ? ? peleTmp->iValue = i;
? ? ? ? ? ? fprintf(stdout,"get element successfully,count = %d.n",i);
? ? ? ? } else {
? ? ? ? ? ? fprintf(stderr,"get element failed,i);
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? i++;
? ? }
? ? /*
? ? ?* 在没有全部回收元素内存的环境下删除内存分区
? ? ?*/
ulError = Lw_Partition_Delete(&_G_hMyPartition); /*无法删除还有未收受接管所有内存*/
? ? if (ulError != ERROR_NONE) {
? ? ? ? fprintf(stderr,"delete partition error.n");
? ? } else {
? ? ? ? return (0);
? ? }
? ? /*
? ? ?* 收受接管内存块返回给内存分区
? ? ?*/
? ? for (i = 0; i < ELEMENT_MAX; i++) {
? ? ? ? peleTmp = peleTable[i];
? ? ? ? if (peleTmp != LW_NULL) {
? ? ? ? ? ? fprintf(stdout,"element%d value = %d.n",i,peleTmp->iValue);
? ? ? ? ? ? peleTmp = Lw_Partition_Put(_G_hMyPartition,peleTmp);
? ? ? ? ? ? if (peleTmp != LW_NULL) {
? ? ? ? ? ? ? ? fprintf(stderr,"element%d put failed.n",i);
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? break;
? ? ? ? }
? ? }
? ? /*
? ? ?* 全部收受接管元素内存后删除内存分区
? ? ?*/
? ? ulError = Lw_Partition_Delete(&_G_hMyPartition); /*? ?可以删除内存分区? ? ? ? ? */
? ? if (ulError != ERROR_NONE) {
? ? ? ? fprintf(stderr,"delete partition error.n");
? ? ? ? return (-1);
? ? } else {
? ? ? ? fprintf(stderr,"delete partition successfully.n");
? ? }
? ? return (0);
}
|
内存分区不直接分配内存,它只是提供了一个管理内存的办法.因此在创建内存分区时,需要指定需要管理的内存,该内存由使用的元素(即上面所述的内存块)大小以及元素的最大个数决定.在程序清单 31中,创建了一个最大可以容纳 8 个类型为MY_ELEMENT 对象的内存分区,然后通过获取元素对象、使用元素对象以及删除内存分区三方面展示了SylixOS 内存分区的使用.该程序运行后,结果如下所示:如图 3-1所示.

图 3-1? 程序运行成果
从运行结果可以看出,最大元素个数为8个,因此第9次获取元素时会失败.随后使用Lw_Partition_Delete函数删除内存分区,由于此时元素还未被回收,因此删除失败.当回收完全部的元素后,能力成功删除.
本文永远更新链接地址: 编程之家PHP培训学院每天发布《LINUX实操:SylixOS 定长内存管理》等实战技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培养人才。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|