热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

实现原理

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

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

__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))

推荐阅读
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有