实现原理
内核堆与系统堆通过内存堆操作库实现,系统会定义两个内存堆指针全局变量,分别指向内核堆和系统堆,接口调用时即通过这两个指针访问内核堆和系统堆。
内核堆和系统堆全局指针定义
__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))