SimpleOS-内存管理
整体设计方案
内存管理模块整体方案如下:
物理内存池划分如下:
虚拟内存池划分如下:
数据结构
//物理内存池
struct pool{
struct bitmap pool_bitmap; //物理内存池位图
uint32_t phy_addr_start; //管理空间起始地址
uint32_t pool_size; //管理空间长度
struct lock lock; //进程申请物理内存时需要上锁
};
//虚拟内存池
struct virtual_addr{
struct bitmap vaddr_bitmap; //虚拟内存池位图
uint32_t vaddr_start; //管理空间起始地址
};
/* 内存块 */
struct mem_block {
struct list_elem free_elem;
};
/* 内存块描述符 */
struct mem_block_desc {
uint32_t block_size; // 内存块大小
uint32_t blocks_per_arena; // 本arena中可容纳此mem_block的数量.
struct list free_list; // 目前可用的mem_block链表
};
/* 内存仓库arena元信息 */
struct arena {
struct mem_block_desc* desc; // 此arena关联的mem_block_desc
uint32_t cnt;
bool large; // large为ture时,cnt表示的是页框数。否则cnt表示空闲mem_block数量
};
内存池提供以页为单位的内存空间
对于每一页内存空间都由元信息arena来组织,并将剩余空间切分成小块
每一个元信息arena组织的内存仓库 都按照块的大小有着相应的mem_block_desc
由mem_block_desc中的free_list来串起所有同一大小的空闲内存块
函数表
kernel/memory.c
//-------------------------------------内存系统初始化相关函数--------------------------- /* @brief: 初始化内存相关数据结构(内存池、内存仓库、内存块描述符) @param: 无 @retval:无 */ void mem_init(); /* @brief: 内存池初始化(物理内核内存池、物理用户内存池、虚拟内核内存池) @param: all_mem:物理内存总量 @retval:无 */ static void mem_pool_init(uint32_t all_mem); /* @brief: 初始化内存块描述符数组(管理7种不同的内存块描述符(16、32、64、128、256、512、1024)) @param: desc_array:要初始化的内存块描述符数组 @retval:无 */ void block_desc_init(struct mem_block_desc* desc_array); //-------------------------------------内存系统初始化相关函数--------------------------- //-------------------------------------内存分配相关函数--------------------------- /* @brief: 分配pg_cnt页的内存空间 @param: pf:内存池类型标识符(内核/用户) pg_nct:申请分配的页数 @retval:成功返回起始虚拟地址,失败返回NULL */ void* malloc_page(enum pool_flags pf,uint32_t pg_cnt); /* @brief: 向虚拟内存池申请pg_cnt页的空间 @param: pf:内存池类型标识符(内核/用户) pg_nct:申请分配的页数 @retval:成功返回起始虚拟地址,失败返回NULL */ static void* vaddr_get(enum pool_flags pf,uint32_t pg_cnt); /* @brief: 向物理内核/用户内存池申请1页空间, @param: m_pool:申请的物理内存池(用户/内核) @retval:成功返回地址起点,失败返回-1 */ static void* palloc(struct pool* m_pool); /* @brief: 建立从虚拟地址到物理地址的映射(以页为单位)(建立相应的页表/页目录) @param: _vaddr:虚拟地址 _page_phyaddr:物理地址 @retval:无 */ static void page_table_add(void* _vaddr,void* _page_phyaddr); /* @brief: 给内核分配pg_cnt页内存, @param: 略 @retval:成功则返回虚拟地址,失败返回NULL */ void* get_kernel_pages(uint32_t pg_cnt); /* @brief: 给用户分配pg_cnt页内存, @param: 略 @retval:成功则返回虚拟地址,失败返回NULL */ void* get_user_pages(uint32_t pg_cnt); /* @brief: 在堆(即内存池)中申请size字节内存(灵活申请) @param: 略 @retval:无 */ void* sys_malloc(uint32_t size); /* @brief: 给指定虚拟地址分配一页内存 @param: pf:内存池表示符 vaddr:指定虚拟地址 @retval:成功则返回虚拟地址,失败返回NULL */ void* get_a_page(enum pool_flags pf,uint32_t vaddr); //-------------------------------------内存分配相关函数--------------------------- //-------------------------------------内存回收相关函数--------------------------- /* @brief: 释放 内核/用户 内存池种以虚拟地址vaddr为起点的cnt个物理页框 @param: pf:内存池标识符 _vaddr:要回收的虚拟地址 pg_cnt:要回收的页数 @retval:无 */ void mfree_page(enum pool_flags pf, void* _vaddr, uint32_t pg_cnt); /* @brief: 将1张物理页回收到物理内存池,实质就是清除物理内存池中位图的位 @param: pg_pyh_addr:要回收页的物理地址 @retval:无 */ void pfree(uint32_t pg_phy_addr); /* @brief: 将以_vaddr起始的连续pg_cnt个虚拟页回收到虚拟内存池,实质就是清除虚拟内存池中位图的位 @param: pf:内存池标识符 _vaddr:要回收的虚拟地址 pg_cnt:要回收的页数 @retval:无 */ static void vaddr_remove(enum pool_flags pf, void* _vaddr, uint32_t pg_cnt) /* @brief: 解除页表中虚拟地址vaddr的映射,实质是将vaddr对应的pte存在位置0 @param: 略 @retval:无 */ static void page_table_pte_remove(uint32_t vaddr); /* @brief: 回收ptr指向的内存块(内存块大小由arena指出) @param: 略 @retval:无 */ void sys_free(void* ptr); //-------------------------------------内存回收相关函数--------------------------- //------------------------------工具函数----------------------------------------- /* @brief: 返回虚拟地址映射的物理地址 @param: 略 @retval:略 */ uint32_t addr_v2p(uint32_t vaddr); /* @brief: 返回arena中第idx个内存块的地址 @param: 略 @retval:略 */ static struct mem_block* arena2block(struct arena* a, uint32_t idx); /* @brief: 返回内存块b所在的arena地址 @param: 略 @retval:略 */ static struct arena* block2arena(struct mem_block* b); /* @brief: 得到虚拟地址vaddr对应的pte指针 @param: 略 @retval:略 */ uint32_t* pte_ptr(uint32_t vaddr); /* @brief: 得到虚拟地址vaddr对应的pde指针 @param: 略 @retval:略 */ uint32_t* pde_ptr(uint32_t vaddr) //------------------------------工具函数-----------------------------------------
关键函数说明
kernel/memory.c/内存分配相关函数
kernel/memory.c/内存回收相关函数
kernel/memory.c/page_table_add()
kernel/memory.c/sys_malloc()