自己动手写操作系统(三)
来源:互联网 发布:jquery java上传文件 编辑:程序博客网 时间:2024/04/30 07:07
这篇文章先乱入一下,这几天一直在写内存分配器(coalition,姑且这么叫吧)。参考的主要还kernel的伙伴内存分配方式。
这里先 一下为什么要用参考伙伴分配方式重新写内存分配器吧。
原先的内存分配设计是采用一个bitmap来记录所有的free page,每次分配都从bitmap里面找4k的页。例如我申请一个16K的内存,我直接找2个4K的页,然后更新PGD表和TLB表,这样的确内存碎片会比较少(基本就没有碎片),但是每次更新TLB表会导致MMU会变慢。而且如果需要的是连续内存,那需要先找到连续的虚拟内存,然后再找连续的物理内存,最后一一映射,速度会变得非常慢。所以这里还是参照kernel的做法,先分了Normal/High两个zone,其中normal zone采用的是平坦映射,即物理地址和虚拟地址一一对应。这块zone上的内存分配就采用了coalition。
目前代码比较简单,主要函数如下:
void coalition_allocator_init(){ int index = 0; //pre-init for(;index < ZONE_FREE_MAX_ORDER;index++) { INIT_LIST_HEAD(&normal_zone.nr_area[index].free_page_list); INIT_LIST_HEAD(&normal_zone.nr_area[index].used_page_list); //normal_zone.nr_area[index].nr_free_pages = 0; } align_result ret; GET_ALIGN_PAGE(_coalition_all_alloc_pages->size,&ret); list_add(&_coalition_all_alloc_pages->ll,&normal_zone.nr_area[ret.order].free_page_list);}初始化4K,16K,32K。。。的队列,由于当前内存还没有被分配过,所以将这块总的内存放入到队列中。
接下来就是内存分配函数,参考buddy的思路,没有找到合适的内存,就需要从更大块分裂出一块。
void* _coalition_malloc(int size) { align_result align_ret; GET_ALIGN_PAGE((size + sizeof(mm_page)),&align_ret); int alignsize = align_ret.page_size; int order = align_ret.order; list_head *p; //we should first find whether there is unused memory list_for_each(p,&normal_zone.nr_area[order].free_page_list) { //优先查找free list,看一下是否有可用的内存 mm_page *page = list_entry(p,mm_page,ll); //we get free page list_del(p); _coalition_list_add(p,&normal_zone.nr_area[order].used_page_list); return page->start_pa + sizeof(mm_page); } //如果没有找到可用的page,那就需要向更大内存的队列查找 //else we should divide a memory from Larger order memory order++; while(order < ZONE_FREE_MAX_ORDER) { int current_order = order; //if(normal_zone.nr_area[order].nr_free_pages > 0) if(!list_empty(&normal_zone.nr_area[order].free_page_list)) { //hit we find a free page,split the page list_for_each(p,&normal_zone.nr_area[order].free_page_list) { mm_page *page = list_entry(p,mm_page,ll); if(page->size < alignsize) { continue; } list_del(p); if(page->size > alignsize) { current_order--; //divide to 2 part,one is used ,another is free. //uint32_t start_pa = get_workable_pa(page); //找到大块可用内存后需要做一次分裂,其中一部分作为free page,放入到free list中 mm_page *another = page->start_pa + alignsize; another->start_pa = another; another->size = page->size - alignsize; align_result another_align_ret; GET_ALIGN_PAGE(another->size,&another_align_ret); //todo int move_order = another_align_ret.order; _coalition_list_add(&another->ll,&normal_zone.nr_area[move_order].free_page_list); _coalition_free_list_adjust(&another->ll,&normal_zone.nr_area[move_order].free_page_list); page->size = alignsize; current_order = align_ret.order;//GET_FREE_ORDER(alignsize); //list_add(p,&normal_zone.nr_area[order - 1].used_page_list); } //另外的一部分就作为used page放入队列中。 //list_add(p,&normal_zone.nr_area[current_order].used_page_list); _coalition_list_add(p,&normal_zone.nr_area[current_order].used_page_list); return page->start_pa + sizeof(mm_page); } } order++; } return NULL;}
内存释放的思路如下:我这里used_page_list/free_page_list是按照地址从小到达排列。所以每次free的时候,只需要确认free page的左右是否有可以合并的即可。合并代码如下:
void _coalition_free_list_adjust(list_head *pos,list_head *head) { align_result align_ret; mm_page *page = list_entry(pos,mm_page,ll); //check prev,we should check whether prev_page is the header? mm_page *prev_page = list_entry(pos->prev,mm_page,ll); if(&prev_page->ll != head) //dnot head { if((page->start_pa - prev_page->start_pa) == page->size) //如果发现前面的page和当前page的地址相差就是page的大小 { list_del(&page->ll); //删除page list_del(&prev_page->ll); prev_page->size += page->size;//合并page,起始就是将前面的page大小放大即可 GET_ALIGN_PAGE(prev_page->size,&align_ret); _coalition_list_add(&prev_page->ll,&normal_zone.nr_area[align_ret.order].free_page_list);//合并好的page插入列表 _coalition_free_list_adjust(&prev_page->ll,&normal_zone.nr_area[align_ret.order].free_page_list);//递归调整 return; } } //check next mm_page *next_page = list_entry(pos->next,mm_page,ll); //printf("adjust next_page is %x size is %x \n",next_page,next_page->size); if(&next_page->ll != head) { if(next_page->start_pa - page->start_pa == page->size) { list_del(&page->ll); list_del(&next_page->ll); page->size += page->size; GET_ALIGN_PAGE(page->size,&align_ret); _coalition_list_add(&page->ll,&normal_zone.nr_area[align_ret.order].free_page_list); _coalition_free_list_adjust(&page->ll,&normal_zone.nr_area[align_ret.order].free_page_list); return; } }}
最后奉上代码的url
https://github.com/wangsun1983/arale/blob/master/core/mm/coalition_alloctor.c
PS:
目前这个内存分配器还没有在arale系统上用,只是本地linux在调试。等测试验证没有问题后,再开启。
谢谢。
阅读全文
0 0
- 自己动手写操作系统(三)
- 自己动手写操作系统(三)
- 自己动手写操作系统(三)
- 自己动手写操作系统(三)
- 自己动手写操作系统(三) 作者:伊梅
- 自己动手写操作系统(三) 作者:伊梅
- 自己动手写操作系统-启动顺序之前三
- 自己动手写OS(操作系统)
- 自己动手写操作系统( 转)
- 自己动手写OS(操作系统)
- 自己动手写操作系统(一)
- 自己动手写操作系统(一)
- 自己动手写操作系统(二)
- 自己动手写操作系统(四)
- 自己动手写操作系统(五)
- 自己动手写操作系统(六)
- 自己动手写操作系统(七)
- 自己动手写俄罗斯方块(三)
- rxjava代码多层转化
- 2017.6.29
- 单片机时钟程序(4)ds1302.c
- 简单ListView 使用
- Android Studio进行JNI开发的操作过程
- 自己动手写操作系统(三)
- Android 使用开源框架实现上传本地文件至服务器
- [JZOJ5179]哈哈
- Boss3g软件开发规范
- 关于mybatis启动报Result Maps collection already contains value for ...的问题总结
- db2icrt创建purescale实例报错:A reachable IP address could not be determined
- Docker简介
- 哈希(poj相关题目)
- CRC检验码