SylixOS 定长内存管理

1. 定长内存管理介绍

所谓定长内存,指的是用户每次分配得到的内存大小是相同的,即便用的是有肯定长度的内存块。同时,这些内存块总的个数也是肯定的,即整个内存总的大小也是肯定的。这和一般理解的内存池的概念是同样的。算法

使用定长内存管理的内存,有两大优势:一是因为事先已经分配好了足够的内存,可极大提升关键应用的稳定性;二是对于定长内存的管理一般有更为简单的算法,分配/释放的效率更高。在SylixOS 中,将管理的一个定长内存称做PARTITION,即内存分区。函数

2. 定长内存管理设置

SylixOS能够经过API操做实现定长内存管理功能。spa

2.1     建立内存分区

#include<SylixOS.h>指针

LW_OBJECT_HANDLE Lw_Partition_Create(CPCHAR            pcName,对象

                                         PVOID             pvLowAddr,blog

                                         ULONG             ulBlockCounter,索引

                                         size_t            stBlockByteSize,进程

                                          ULONG             ulOption,内存

                                         LW_OBJECT_ID      *pulId)ci

函数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所示。

wKioL1k_1rbw6tMRAACbikiwjYc290.png

图 3-1  程序运行结果

从运行结果能够看出,最大元素个数为8个,所以第9次获取元素时会失败。随后使用Lw_Partition_Delete函数删除内存分区,因为此时元素还未被回收,所以删除失败。当回收彻底部的元素后,才能成功删除。

相关文章
相关标签/搜索