sylixos定长内存管理

author author     2022-09-04     485

关键词:

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 的属性。

SylixOSLw_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 函数获得)返回给内存分区。

注:如果pvBlockNULL,则设置错误号为 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. ");

        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. ", i);

        } else {

            fprintf(stderr, "get element failed, count = %d. ", i);

            break;

        }

        i++;

    }

    /*

     * 在没有全部回收元素内存的情况下删除内存分区

     */

ulError = Lw_Partition_Delete(&_G_hMyPartition); /*无法删除还有未回收所有内存*/

    if (ulError != ERROR_NONE) {

        fprintf(stderr, "delete partition error. ");

    } else {

        return (0);

    }

    /*

     * 回收内存块返回给内存分区

     */

    for (i = 0; i < ELEMENT_MAX; i++) {

        peleTmp = peleTable[i];

        if (peleTmp != LW_NULL) {

            fprintf(stdout, "element%d value = %d. ", i, peleTmp->iValue);

            peleTmp = Lw_Partition_Put(_G_hMyPartition, peleTmp);

            if (peleTmp != LW_NULL) {

                fprintf(stderr, "element%d put failed. ", i);

            }

        } else {

            break;

        }

    }

    /*

     * 全部回收元素内存后删除内存分区

     */

    ulError = Lw_Partition_Delete(&_G_hMyPartition); /*   可以删除内存分区           */

    if (ulError != ERROR_NONE) {

        fprintf(stderr, "delete partition error. ");

        return (-1);

    } else {

        fprintf(stderr, "delete partition successfully. ");

    }

    return (0);

}

内存分区不直接分配内存,它只是提供了一个管理内存的方法。因此在创建内存分区时,需要指定需要管理的内存,该内存由使用的元素(即上面所述的内存块)大小以及元素的最大个数决定。在程序清单 31中,创建了一个最大可以容纳 8 个类型为MY_ELEMENT 对象的内存分区,然后通过获取元素对象、使用元素对象以及删除内存分区三方面展示了SylixOS 内存分区的使用。该程序运行后,结果如下所示: 3-1所示。

技术分享

3-1  程序运行结果

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


本文出自 “12548035” 博客,请务必保留此出处http://12558035.blog.51cto.com/12548035/1935132

简单实现定长内存池(代码片段)

目录前言一.定长内存池    1.1概念    1.2实现    1.2.1成员变量介绍    1.2.2成员函数介绍     1.2.3细节    1.3代码前言    我们知道用户申请内存必须通过操作系统,操作系统再从堆上开辟一段空间给用户。但... 查看详情

sylixos内存性能测试程序设计与实现

1.内存性能测试需求        SylixOS作为大型实时操作系统,在各个领域当中都会有重要应用。其中,在高性能运算领域需要较高的内存读写性能,因此我们需要有一个直观,跨平台的内存测试软件来给... 查看详情

sylixos标准工程移植到lite版本

...理器(如ARMM系列处理器)的开发工作,翼辉信息推出了SylixOSLite工程版本。SylixOSLite版本工程属于SylixOS轻量级工程,与标准的SylixOS工程相比裁剪掉部分功能(如GDB调试、虚拟内存管理、动态装载、部分网络功能等)。  ... 查看详情

sylixos内存错误排查方法

 1.应用程序测试代码 测试代码如程序清单1.1所示:程序清单1.1#include<stdio.h>  intmain(intargc,char**argv){sleep(2);volatileint*a=(int*)0x40;//设置物理地址  printf("value=%x ",*a);//读取物理地址中的值*a=0x12;//设置物理地址中的 查看详情

sylixos电源管理之外设功耗管理

...算机的世界里称作电源管理(PowerManagement)。本篇以运行SylixOS的mini2440嵌 查看详情

sylixos中ppc架构系列介绍-cache篇

...CPU与内存间的一种容量较小但速度很高的存储器。 2.SylixOS中Cache架构SylixOS中为了对Cache进行有效的管理,提 查看详情

简单内存池与定长内存池(代码片段)

目录内存碎片最简单的内存池申请释放定长内存池哈希映射的freelist池实现定长内存池内存碎片最简单的内存池申请释放定长内存池哈希映射的freelist池内碎片对比内碎片与外碎片实现定长内存池成员变量 private: //一大块内存 //... 查看详情

简单内存池与定长内存池(代码片段)

目录内存碎片最简单的内存池申请释放定长内存池哈希映射的freelist池实现定长内存池内存碎片最简单的内存池申请释放定长内存池哈希映射的freelist池内碎片对比内碎片与外碎片实现定长内存池成员变量 private: //一大块内存 //... 查看详情

sylixos多路网卡冗余管理简介

...网络的可靠性,实现冗余设备热切换是一种常见的方法。SylixOS支持的多路网卡冗余管理模块是一款网卡故障保护管理模块。它提供一种故障保护机制,对网络设备进行冗余备份,当其中一个设备由于某种原因不能正常工作时,... 查看详情

sylixos磁盘高速传输

SylixOS管线模型分析前文主要介绍了SylixOS中的块设备CACHE管理,本章主要介绍磁盘高速传输。在CAHCE回写中SyilxOS采取了两种方式,即直接回写和多管线并发回写。并发写管线通过多线程并发处理CACHE提交的写请求,实现磁盘高速传... 查看详情

swift值类型和引用类型的内存管理(代码片段)

1、内存分配1.1值类型的内存分配在Swift中定长的值类型都是保存在栈上的,操作时不会涉及堆上的内存。变长的值类型(字符串、集合类型是可变长度的值类型)会分配堆内存。这相当于一个“福利”,意味着你可以使用值类型... 查看详情

stm32内存管理(代码片段)

...内存占空闲内存总和的比例越大越好动态内存管理的分类定长内存管理将内存分为大小相同的单元,每次申请一个单元的内存变长内存管理每次申请需要的内存(大小不固定,以字节为单位)定长内存管理的设计... 查看详情

sylixos中arm架构的mmu实现分析(代码片段)

1.理论知识1.1快表(TLB)与页表在虚拟页式存储管理中设置了快表(TLB),用于保存正在运行进程页表的子集,通常快表存放在高速缓冲存储器(Cache)中。而页表存放在内存中,并通过特殊功能寄存器(TTB)等告知系统页表存... 查看详情

sylixos中断系统分析

SylixOS中断系统分析中断向量表在SylixOS中,系统默认存在一张大小为256(可以手动配置)的中断向量表,用于管理SylixOS中的每一个中断向量。该向量表存在于k_globalvar.h文件中,其定义格式如程序清单1-1所示。程序清单1-1系统中... 查看详情

sylixos字符设备驱动框架

1、概述本文档主要介绍SylixOS中字符设备驱动框架,适用于在SylixOS集成开发环境下进行字符设备驱动开发的学习。注:文中xxx是指具体设备名,编写对应驱动时,自行命名(如RTC、COMPASS等)。2、SylixOS字符设备驱动简介字符设备... 查看详情

c++项目定长内存池(代码片段)

解决固定大小的内存申请释放需求性能达到极致,不考虑内存碎片等问题第一次: #include<iostream>usingstd::cout;usingstd::endl;template<classT>classObjectPoolpublic: T*New() if(RemainBytes<sizeof(T))//如果剩余的内存不足一 查看详情

sylixos下内核线程简介

...程则共享使用进程内所有资源,例如进程文件描述符表。SylixOS对于一些系统级功能是通过使用内核线程进行管理使用。2.内核线程   基于SylixOS的1.5.3的内核,在终端上输入命令“ts”如图2.1所示。图2.1 “ts”命令2.... 查看详情

syilxos块设备cache管理

1.块设备CACHE简介     前文介绍了SylixOS中的块设备驱动模型和I/O控制,本篇主要介绍SylixOS中的块设备CACHE管理。由于磁盘属于低速设备,磁盘的读写速度远远低于CPU,所以为了解决这种速度不匹配,SylixOS提供了... 查看详情