欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-24 11:46:40
...

    今天主要分析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数组
相关标签: 操作系统