SylixOS中的动态内存分配【5】--- 内核堆与系统堆实现原理详解

实现原理

内核堆与系统堆通过内存堆操作库实现,系统会定义两个内存堆指针全局变量,分别指向内核堆和系统堆,接口调用时即通过这两个指针访问内核堆和系统堆。

内核堆和系统堆全局指针定义。

__KERNEL_EXT PLW_CLASS_HEAP          _K_pheapKernel;                    /*  内核堆                      */
__KERNEL_EXT PLW_CLASS_HEAP          _K_pheapSystem;                    /*  系统堆                      */

初始化
内核初始化时会指定内核堆和系统堆的起始地址和大小,然后通过_HeapCreate接口进行初始化。可以不指定系统堆的起始地址和大小,此时系统堆指针会被初始化为内核堆指针,即系统堆实际等同于内核堆。大部分情况下,是不对系统堆指定起始地址和大小的。

/*********************************************************************************************************
** 函数名称: _HeapKernelInit
** 功能描述: 内核堆内存初始化
** 输 入  : pvKernelHeapMem   内核堆的起始地址
**           stKernelHeapSize  内核堆的大小
** 输 出  : NONE
*********************************************************************************************************/
VOID  _HeapKernelInit (PVOID     pvKernelHeapMem,
                       size_t    stKernelHeapSize)                                                                 /*  LW_CFG_MEMORY_HEAP_...      */
{
    PVOID   pvHeap;
    size_t  stSize;

    pvHeap = pvKernelHeapMem;
    stSize = stKernelHeapSize;
    
    _K_pheapKernel = _HeapCreate(LW_KERNEL_HEAP_START(pvKernelHeapMem), 
                                 LW_KERNEL_HEAP_SIZE(stKernelHeapSize));

    lib_strcpy(_K_pheapKernel->HEAP_cHeapName, "kernel");
}
/*********************************************************************************************************
** 函数名称: _HeapSystemInit
** 功能描述: 系统堆内存初始化
** 输 入  : pvSystemHeapMem   系统堆的起始地址
**           stSystemHeapSize  系统堆的大小
** 输 出  : NONE
** 输 出  : 
*********************************************************************************************************/
VOID  _HeapSystemInit (PVOID     pvSystemHeapMem,
                       size_t    stSystemHeapSize)
{
    if (pvSystemHeapMem && stSystemHeapSize) {
        _K_pheapSystem = _HeapCreate(pvSystemHeapMem, stSystemHeapSize);
    } else {
        _K_pheapSystem = _K_pheapKernel;                                /*  只使用 kernel heap          */
    }

    if (_K_pheapSystem == _K_pheapKernel) {
        lib_strcpy(_K_pheapSystem->HEAP_cHeapName, "kersys");
    
    } else {
        lib_strcpy(_K_pheapSystem->HEAP_cHeapName, "system");
    }
}

初始化调用流程:
在这里插入图片描述
一般情况下,会将DATA分区中除去.data段、.bss段、.stack段外的所有剩余空间用作内核堆(.heap)。起始地址为(PVOID)&__heap_start,内存大小为(size_t)&__heap_end - (size_t)&__heap_start,这部分内存的分配是通过连接脚本SylixOSBSP.ld中实现的。而系统堆则不指定内存空间。

SylixOSBSP.ld中DATA分区配置如下:

/*********************************************************************************************************
    .data 段数据初始化内容放在这里
*********************************************************************************************************/

    . = ALIGN(8);
    PROVIDE (_etext = .);

/*********************************************************************************************************
     数据段

     .data 段运行地址 VMA 为 ORIGIN(DATA), 装载地址 LMA 为 _etext,
     连接器会将 .data 的初始化数据放在 _etext 的地方, 然后启动程序必须将 _etext 的内容搬运到 
     VMA ORIGIN(DATA) 中. 大小等于 SIZEOF(.data)
*********************************************************************************************************/

    .data ORIGIN(DATA) : AT (_etext) {
        . = ALIGN(8);
        PROVIDE (_data = .);
        
        *(.data)
        *(.sdata)
        *(.sbss)
        *(.scommon)

        . = ALIGN(8);
        PROVIDE (_edata = .);
    } > DATA
    
/*********************************************************************************************************
    清零段

    NOLOAD 表示不装载, 启动程序只需要借助 __bss_start 和 __bss_end 两个符号指定的起始地址和结束地址
    将 .bss 区域清零即可. (注意 *.noinit 可以不进行清零)
*********************************************************************************************************/

    .bss (NOLOAD) : {
        . = ALIGN(8);
        *(.noinit)
        
        . = ALIGN(8);
        PROVIDE (__bss_start = .);
        
        *(.bss)
        
        . = ALIGN(8);
        *(COMMON)
        
        . = ALIGN(8);
        PROVIDE (__bss_end = .);
    } > DATA

/*********************************************************************************************************
    栈段
    
    SylixOS 启动时使用,异常入口也使用
*********************************************************************************************************/

    .stack (NOLOAD) : {
        . = ALIGN(8);
        PROVIDE (__stack_start = .);
        
        . += BOOT_STACK_SIZE;
        
        . = ALIGN(8);
        PROVIDE (__stack_end = .);
    } > DATA
    
/*********************************************************************************************************
    内核堆段
*********************************************************************************************************/

    .heap (NOLOAD) : {
        . = ALIGN(8);
        PROVIDE (__heap_start = .);
        
        __heap_end = ORIGIN(DATA) + LENGTH(DATA) - 128;
        PROVIDE (__heap_end = .);
    } > DATA

内核堆和系统堆在初始化后即可进行使用,以宏函数为接口,通过内存堆操作库实现。注意,内核堆和系统堆是不会被删除的,也不会被扩展。

内核堆接口宏:

#define __KHEAP_ALLOC(stNBytes)                 _HeapAllocate(_K_pheapKernel, stNBytes, __func__)
#define __KHEAP_ZALLOC(stNBytes)                _HeapZallocate(_K_pheapKernel, stNBytes, __func__)
#define __KHEAP_REALLOC(pvMemory, stNBytes)     _HeapRealloc(_K_pheapKernel, pvMemory, stNBytes, LW_FALSE, __func__)       
#define __KHEAP_ALLOC_ALIGN(stNBytes, stAlgin)  _HeapAllocateAlign(_K_pheapKernel, stNBytes, stAlgin, __func__)        
#define __KHEAP_FREE(pvMemory)                  _HeapFree(_K_pheapKernel, pvMemory, LW_FALSE, __func__)

#define ker_malloc(size)                		__KHEAP_ALLOC((size_t)(size))
#define ker_zalloc(size)                		__KHEAP_ZALLOC((size_t)(size))
#define ker_free(p)                     		__KHEAP_FREE((p))
#define ker_realloc(p, new_size)        		__KHEAP_REALLOC((p), (size_t)(new_size))
#define ker_malloc_align(size, align)   		__KHEAP_ALLOC_ALIGN((size_t)(size), (size_t)(align))

系统堆接口宏:

#define __SHEAP_ALLOC(stNBytes)                 _HeapAllocate(_K_pheapSystem, stNBytes, __func__)
#define __SHEAP_ZALLOC(stNBytes)                _HeapZallocate(_K_pheapSystem, stNBytes, __func__)
#define __SHEAP_REALLOC(pvMemory, stNBytes)     _HeapRealloc(_K_pheapSystem, pvMemory, stNBytes, LW_FALSE, __func__)
#define __SHEAP_ALLOC_ALIGN(stNBytes, stAlgin)  _HeapAllocateAlign(_K_pheapSystem, stNBytes, stAlgin, __func__)
#define __SHEAP_FREE(pvMemory)                  _HeapFree(_K_pheapSystem, pvMemory, LW_FALSE, __func__)

#define sys_malloc(size)                		__SHEAP_ALLOC((size_t)(size))
#define sys_zalloc(size)                		__SHEAP_ZALLOC((size_t)(size))
#define sys_free(p)                     		__SHEAP_FREE((p))
#define sys_realloc(p, new_size)        		__SHEAP_REALLOC((p), (size_t)(new_size))
#define sys_malloc_align(size, align)   		__SHEAP_ALLOC_ALIGN((size_t)(size), (size_t)(align))
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ScilogyHunter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值