自己动手写操作系统(七)

    今天主要分析coalition_allocator的内存分配流程。看过linux相关数据的同学都听说过kernel的buddy内存管理。实际上coalition内存分配的远离和buddy基本相同:将物理内存分为4k,8k,16k,32k......2的幂。例如,目前需要分配一个9k的内存,步骤如下:

========================================

1.调用GET_ALIGN_PAGE向上取整,最后变为申请一个16k的内存。

2.在16k的free_page_list查询是否有空余内存,如果有,直接返回该内存

3.如果16k的free_page_list中没有,则向上查询32k的free_page_list是否存在空余内存。

4.查到空余内存后,以64k为例子,直接将空余内存分割成16k和48k

5.48k继续调用_coalition_free_list_adjust去做调整。

========================================

代码如下:

void* _coalition_malloc(int type,uint32_t size)
{
    align_result align_ret;
    int addr_shift = sizeof(pmm_stamp);

    if(type == PMM_TYPE_PMEM)
    {
        addr_shift = PAGE_SIZE;
    }

    GET_ALIGN_PAGE((size + addr_shift),&align_ret); //向上取整为2的n次幂

    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) {//如果当前的存在剩余内存可用,直接返回即可

        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);
        pmm_stamp *ret_stamp = (pmm_stamp *)page->start_pa;
        ret_stamp->type = type;

        return (void *)(page->start_pa + addr_shift);
    }

    order++;//没有找到剩余内存,继续向更大的内存队列查询

    while(order < ZONE_FREE_MAX_ORDER)
    {
       int current_order = order;

       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)//发现当前的可用内存可以分配出制定的内存大小
               {
                   pmm_stamp *stamp = (pmm_stamp *)(page->start_pa + alignsize);
                   mm_page *another = &stamp->page;
                   //kprintf("wangsl2,anotheris %x,alignsize is %x \n",another,alignsize);
                   another->start_pa = (addr_t)stamp;
                   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;//将内存分为2块,一块就是所需要的内存,一块剩余内存放入free page list
                   _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);
                   //free page list重新做归并
                   page->size = alignsize;
                   current_order = align_ret.order;//GET_FREE_ORDER(alignsize);
               }

               _coalition_list_add(p,&normal_zone.nr_area[current_order].used_page_list);//已经使用的内存放入used数组

猜你喜欢

转载自blog.csdn.net/wang_sun_1983/article/details/77939324