SylixOS 定长内存管理
来源:互联网 发布:西门子工控淘宝旗舰店 编辑:程序博客网 时间:2024/06/07 21:42
1. 定长内存管理介绍
所谓定长内存,指的是用户每次分配获得的内存大小是相同的,即使用的是有确定长度的内存块。同时,这些内存块总的个数也是确定的,即整个内存总的大小也是确定的。这和通常理解的内存池的概念是一样的。
使用定长内存管理的内存,有两大优点:一是由于事先已经分配好了足够的内存,可极大提高关键应用的稳定性;二是对于定长内存的管理通常有更为简单的算法,分配/释放的效率更高。在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 内存分区创建选项
选项名称
解释
LW_OPTION_OBJECT_GLOBAL
表示该对象为一个内核全局对象
LW_OPTION_OBJECT_LOCAL
表示该对象仅为一个进程拥有,即本地对象
LW_OPTION_DEFAULT
默认选项
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, count = %d.\n",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函数删除内存分区,由于此时元素还未被回收,因此删除失败。当回收完全部的元素后,才能成功删除。
- SylixOS 定长内存管理
- SylixOS内存泄漏检测
- SylixOS内存错误排查方法
- SylixOS块设备CACHE管理
- SylixOS电源管理之外设功耗管理
- SylixOS KN_SMP_WMB()内存屏障函数解析
- 定长内存池之BOOST::pool
- 定长内存池之BOOST::pool
- SylixOS电源管理概述以及接口介绍
- SylixOS调试与性能分析技术--内存泄漏检测
- 定长单元的批次内存缓存池的简洁实现
- 基于一个简单定长内存池的实现方法详解
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 474. Ones and Zeroes
- Git的操作
- Draw a Parametric Curve
- GO之旅(3)
- 关于float有效位数为7位的研究
- SylixOS 定长内存管理
- uva 10082
- iOS-音频
- 页框page
- Python字符串处理:按单词反转
- 8. String to Integer (atoi)
- iOS-视频
- Java知识小结—(1)
- Hadoop学习笔记十一 使用Oozie自动化数据处理(未完)