12.7规划内存空间的分配

本文讲述了在嵌入式系统中如何规划内存空间,包括操作系统内核区和进程使用的内存区域。作者详细介绍了如何通过`show_mem_info`和`total_mem_size`函数获取内存信息,以及如何利用位图技术管理和初始化内存管理系统,确保内存的有效分配。
摘要由CSDN通过智能技术生成

12.7规划内存空间的分配

1MB以下给操作系统内核区使用,位图的uint8数组放在kernel后面(怎么找到kernel后面这个地址很有技巧)

1MB以上的内存给进程使用

我们需要知道可用内存的细节

//memory.c
//打印空闲区域的信息,分块打印
static void show_mem_info (boot_info_t * boot_info) {
    log_printf("mem region:");
    for (int i = 0; i < boot_info->ram_region_count; i++) {
        log_printf("[%d]: 0x%x - 0x%x", i, 
                    boot_info->ram_region_cfg[i].start,
                    boot_info->ram_region_cfg[i].size);
    }
    log_printf("\n");
}

/**
 * @brief 获取整个可用的物理内存大小
 */
static uint32_t total_mem_size(boot_info_t * boot_info) {
    int mem_size = 0;

    // 简单起见,暂不考虑中间有空洞的情况
    for (int i = 0; i < boot_info->ram_region_count; i++) {
        mem_size += boot_info->ram_region_cfg[i].size;
    }
    return mem_size;
}

对空闲区域的内存进行位图化

/**
 * @brief 初始化内存管理系统
 */
void memory_init (boot_info_t * boot_info) {
    // 位图存放的位置
    extern uint8_t * mem_free_start;  //从source\kernel\kernel.lds中取出kernel末尾的地址,如下代码

    log_printf("mem init.");
    show_mem_info(boot_info);

    // 在内核数据后面放物理页位图
    uint8_t * mem_free = (uint8_t *)&mem_free_start;   // 这个地方又加个&让我着实不太了解,这个地方是链接器要求的,先取地址再取值

    // 计算1MB以上空间的空闲内存容量,并对齐的页边界
    uint32_t mem_up1MB_free = total_mem_size(boot_info) - MEM_EXT_START; //1MB内存的地址
    mem_up1MB_free = down2(mem_up1MB_free, MEM_PAGE_SIZE);   // 需要对齐到4KB页大小
    log_printf("Free memory: 0x%x, size: 0x%x", MEM_EXT_START, mem_up1MB_free);

    // 4GB大小需要总共4*1024*1024*1024/4096/8=128KB的位图, 使用1MB的RAM空间中足够
    // 该部分的内存仅跟在mem_free_start开始放置
    addr_alloc_init(&paddr_alloc, mem_free, MEM_EXT_START, mem_up1MB_free, MEM_PAGE_SIZE);
    mem_free += bitmap_byte_count(paddr_alloc.size / MEM_PAGE_SIZE);

    // 到这里,mem_free应该比EBDA地址要小
    ASSERT(mem_free < (uint8_t *)MEM_EBDA_START);
}

source\kernel\kernel.lds

SECTIONS
{
    . = 0x10000;

	.text : {
		*(.text)
	} 

	.rodata : {
		*(.rodata)
	}
	
	.data : {
		*(.data)
	}
	
	.bss : {
		*(.bss)
	}
	
	PROVIDE(mem_free_start = .); //取出.bss后面的地址,这和链接器提供的功能有关
}

memory.h

#define MEM_EBDA_START              0x00080000 //那个不可访问区域(显存等保留区域)的起始地址
#define MEM_EXT_START               (1024*1024) //1MB
#define MEM_PAGE_SIZE               4096        // 和页表大小一致,4KB

klib.h

// 对齐函数写成内联函数
// 向上对齐到页边界,向上对齐
static inline uint32_t up2 (uint32_t size, uint32_t bound) {
    return (size + bound - 1) & ~(bound - 1);
}

// 向下对齐到界边界
static inline uint32_t down2 (uint32_t size, uint32_t bound) { //转换为bound的整数倍,向下取整
    return size & ~(bound - 1);
}
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值