babyos2(11)——物理内存管理,伙伴系统
来源:互联网 发布:淘宝打针织打底衫长款 编辑:程序博客网 时间:2024/06/06 04:44
由于babyos2采用了类似于linux的获取current进程指针的方法,这要求process_t的内存按8K对齐,继续采用boot阶段m_start_mem递增的方式就很笨拙了,而要实现后续的vma,虚拟内存管理等功能,一个好用的物理页分配函数是必须的,所以实现了一个buddy system来管理物理内存。
#define MAX_ORDER 6#define MAP_NR(addr) (((unsigned long)(addr)) >> PAGE_SHIFT)typedef struct page_s { struct page_s* next; struct page_s* prev;} page_t;typedef struct free_list_s { struct free_list_s* next; struct free_list_s* prev; unsigned* map;} free_list_t;typedef struct free_area_s { free_list_t free_list[MAX_ORDER+1]; unsigned char* base;} free_area_t;
用于管理的数据结构比较简单,每个area有若干个free_list及一个base address,每个free_list是一个链表加一个bitmap,bitmap用于方便看自己的buddy是否空闲。
void mm_t::init_free_area(){ uint32 mask = PAGE_MASK; uint32 bitmap_size; for (int i = 0; i <= MAX_ORDER; i++) { m_free_area.free_list[i].prev = m_free_area.free_list[i].next = &m_free_area.free_list[i]; mask += mask; m_mem_end = (uint8 *)(((uint32)m_mem_end) & mask); bitmap_size = (uint32 (m_mem_end - m_mem_start)) >> (PAGE_SHIFT + i); bitmap_size = (bitmap_size + 7) >> 3; bitmap_size = (bitmap_size + sizeof(uint32) - 1) & ~(sizeof(uint32)-1); m_free_area.free_list[i].map = (uint32 *) m_mem_start; memset((void *) m_mem_start, 0, bitmap_size); m_mem_start += bitmap_size; } m_free_area.base = (uint8*)(((uint32)m_mem_start + ~mask) & mask);}
m_free_area的初始化,依次初始化每个free_list的表头及为bitmap分配空间。
void mm_t::free_pages(void* addr, uint32 order){ uint32 address = (uint32) addr; uint32 index = MAP_NR(address - (uint32)m_free_area.base) >> (1 + order); uint32 mask = PAGE_MASK << order; address &= mask; while (order < MAX_ORDER) { if (!change_bit(index, m_free_area.free_list[order].map)) { break; } uint32 buddy = get_buddy(address, mask); remove_head(m_free_area.free_list+order, (free_list_t *)buddy); order++; index >>= 1; mask <<= 1; address &= mask; } add_to_head(m_free_area.free_list+order, (free_list_t *) address);}uint32 mm_t::get_buddy(uint32 addr, uint32 mask){ uint32 buddy = ((addr - (uint32)m_free_area.base) ^ (-mask)) + (uint32)m_free_area.base; return buddy;}int mm_t::mark_used(uint32 addr, uint32 order){ return change_bit(MAP_NR(addr - (uint32)m_free_area.base) >> (1+order), m_free_area.free_list[order].map);}
释放页,释放时会查找自己的buddy释放已空闲,若已空闲则合并为一个更高order的块并继续向上合并。
void* mm_t::expand(free_list_t* addr, uint32 low, uint32 high){ uint32 size = PAGE_SIZE << high; while (low < high) { high--; size >>= 1; add_to_head(m_free_area.free_list+high, addr); mark_used((uint32) addr, high); addr = (free_list_t *) (size + (uint32) addr); } return addr;}void* mm_t::alloc_pages(uint32 order){ free_list_t* queue = m_free_area.free_list + order; uint32 new_order = order; do { free_list_t* next = queue->next; if (queue != next) { queue->next = next->next; next->next->prev = queue; mark_used((uint32) next, new_order); return expand(next, order, new_order); } new_order++; queue++; } while (new_order <= MAX_ORDER); return NULL;}
分配过程则相反,从当前所要求的order开始找,若无空闲,则向上找,找到后依次向下拆分,然后分配所要求的order的页。
int32 sys_exec(trap_frame_t* frame){ // 1. read init from hd clb1.flags = 0; clb1.read = 1; clb1.dev = 0; clb1.lba = 512; memset(clb1.buffer, 0, 512); os()->get_ide()->request(&clb1); // 2. allocate a page and map to va 0-4k, pde_t* pg_dir = os()->get_mm()->get_pg_dir(); void* mem = os()->get_mm()->alloc_pages(1); uint32* p = (uint32 *) 0; os()->get_mm()->map_pages(pg_dir, p, VA2PA(mem), 2*PAGE_SIZE, PTE_W | 0x04); // 3. load init to 0x0 memcpy(p, clb1.buffer, 512); // frame frame->cs = (SEG_UCODE << 3 | 0x3); frame->ds = (SEG_UDATA << 3 | 0x3); frame->es = (SEG_UDATA << 3 | 0x3); frame->ss = (SEG_UDATA << 3 | 0x3); frame->fs = (SEG_UDATA << 3 | 0x3); frame->gs = (SEG_UDATA << 3 | 0x3); // eip & esp frame->eip = 0; // need get eip by load elf and get address frame->esp = PAGE_SIZE*2; return 0;}
修改了exec系统调用的代码,使用伙伴系统分配内存。
阅读全文
0 0
- babyos2(11)——物理内存管理,伙伴系统
- Linux内存管理——伙伴系统
- linux内核内存管理学习之二(物理内存管理--伙伴系统)
- linux内核内存管理学习之二(物理内存管理--伙伴系统)
- linux内核内存管理学习之二(物理内存管理--伙伴系统)
- linux内核内存管理学习之二(物理内存管理--伙伴系统)
- linux内核内存管理学习之二(物理内存管理--伙伴系统)
- babyos2(9)——系统调用
- 内存管理---伙伴系统---
- 内存管理-----伙伴系统---2
- linux内存管理之伙伴系统(内存分配)
- Linux内存管理之伙伴系统(内存释放)
- Linux内存管理之伙伴系统(内存释放)
- linux内存管理之伙伴系统(内存分配)
- 伙伴系统之伙伴系统概述--Linux内存管理(十五)
- linux内存管理之伙伴系统(建立)
- linux内存管理之伙伴系统(建立)
- Linux系统内存管理之伙伴系统分析
- 汇编---将输入的字符数字转化为二进制数据
- java线程安全之Executor框架及自定义线程池(十五)
- 第一次学电路的艰苦旅程
- 正则 gerp
- 使用selenium3.X启动chrome浏览器
- babyos2(11)——物理内存管理,伙伴系统
- 分布式
- block使用小结、在arc中使用block、如何防止循环引用(zz)
- spring技术内幕读书笔记--springmvc组件
- Struts2应用(一)
- sublime3写java
- mysql错误代码表
- react-native 播放声音
- 习题7.3