Buddy_Zhang1 发表于 2016-03-02 16:53

[73%]正在写一个模拟 Linux 内存管理的系统

本帖最后由 Buddy_Zhang1 于 2016-03-24 20:38 编辑

我想写一个关于内存管理的小系统,该系统的内存管理机制完全模拟 Linux 的内存管理机制.

我的想法是在用户空间申请两个大小为 256M 的数组,然后把这两个数组模拟成两块内存块,
我就基于这两块虚拟内存块,在其上面构建一个和 Linux 内存管理机制一样的系统.
这个系统是运行在用户空间的,也就是一个用户程序而已!

这样是否可行?大家提提意见.

写这个系统的目的就是学习 Linux 内存管理从创建到运行管理的整个过程,如果可行,并且写出来,我会开源出来.

谢谢!{:yxh45:}

Buddy_Zhang1 发表于 2016-03-03 08:41

本帖最后由 Buddy_Zhang1 于 2016-03-04 11:47 编辑

经过考虑,我做以下模拟:
1. 硬件模拟支持 MMU 的 ARMv7
2. 使用纯 C 编写.
3. 使用 main() 函数的构造函数作为 Uboot,使用 main() 作为 kernel 空间.
4. 单核 UMA
5. 两块模拟内存块之间存在一定大小 hole.
{:yxh45:}

Buddy_Zhang1 发表于 2016-03-04 11:45

Feature Update:
该内存管理系统支持内存分配器如下:
1. Bootmem Allocator
2. Per-CPU Allocator
3. Buddy Allocator
4. PCP Allocator
5. SLUB Allocator
6. VMALLOC Allocator
7. KMAP Allocator
{:yxh45:}

nswcfd 发表于 2016-03-04 18:00

赞!+U!

PS,为啥需要模拟硬件,哪些逻辑跟arch相关?

Buddy_Zhang1 发表于 2016-03-04 21:06

本帖最后由 Buddy_Zhang1 于 2016-03-04 21:08 编辑

回复 4# nswcfd


主要是模拟硬件 MMU 和页表转换过程,其中 setup_arch() 函数中比较多
和 arch 关系最大的当属 Bootmem Allocator 了


   

Buddy_Zhang1 发表于 2016-03-06 12:04

本帖最后由 Buddy_Zhang1 于 2016-03-06 12:04 编辑

Feature Update:
核心算法支持:
1. 红黑树
2. 优先查找树
3. 基数树.
4. HASH
5. 伙伴系统算法
{:yxh45:}

Buddy_Zhang1 发表于 2016-03-07 12:08

技术问题:
我使用的是 64 位的系统,但我写的系统是一个 32 位的系统,所以在 64 位用户空间模拟 32 位程序是一个难题.

大家有没相应的经验,交流一下.
{:yxh45:}

Buddy_Zhang1 发表于 2016-03-08 10:42

Feature Update:
伙伴系统算法更新:
从伙伴系统中获得一个物理页:

struct TestCase_get_free_page(void)
{
   struct pglist_data *pgdat;
   struct zonelist *zonelist;
   struct zone *zone;
   struct free_area *area;
   struct page *page;
   int migratetype;
   int order,current_order;

   pgdat = NODE_DATA(0);
   zonelist = pgdat->node_zonelists;
   first_zones_zonelist(zonelist,0,NULL,&zone);
   migratetype = MIGRATE_MOVABLE;
   int order = 0;

   for(current_order = 0 ; current_order < MAX_ORDER ; current_order++) {
         unsigned long size;

         area = &zone->free_area;
         if(list_empty(&area->free_list))
                      continue;
   
         page = list_entry(area->free_list.next,
                              struct page,lru);
         list_del(&page->lru);
         rmv_page_order(page);
         area->nr_free--;
         
         size = 1 << current_order;
         while(order < current_order) {
                ara--;
                current_order--;
                size >>= 1;
                list_add(&page,lru,
                              &area->free_list);
                set_page_order(&page,current_order);
                area->nr_free++;
          }
          if(!PageBuddy(page))
               goto out;
   }
   printk(KERN_INFO "Can't get free page\n");
   return;

out:
      printk(KERN_INFO "Get free page\n");
}

释放一个 page 回伙伴系统

void TestCase_free_page(void)
{
      struct page *page = /* 已知*/;
      struct zone *zone;
      struct page *buddy;
      unsigned long page_idx,buddy_idx;
      unsigned long combine_idx;
      int order = 0;

   zone = page_zone(page);
   migratetype = get_pageblock_migratetype(page);
   page_idx = page_to_pfn(page);

   while(order < MAX_ORDER-1) {
         buddy_idx = __find_buddy_index(page_idx,order);
         buddy = page + (buddy_idx - page_idx);
         if(!page_is_buddy(page,buddy,order))
                  break;

         list_del(&buddy.lru);
         rmv_page_order(buddy);
         zone->free_area.nr_free--;
         combine_idx = buddy_idx & page_idx;
         page = page + (combine_idx - page_idx);
         page_idx = combine_idx;
         order++;
    }
    set_page_order(page,order);

    if((order < MAX_ORDER - 2) && (pfn_valid_within(page_to_pfn(page)))) {
          struct page *higher_page,*higher_buddy;

          combine_idx = buddy_idx & page_idx;
          higher_page = page + (combine_idx - page_idx);
          buddy_idx = __find_buddy_index(combine_idx,order + 1);
          higher_buddy = higher_page + (buddy_idx - combine_idx);
          if(page_is_buddy(higher_page,higher_buddy,order + 1)) {
                   list_add_tail(&page->lru,
                      &zone->free_area.free_list);
                   goto out;
          }
    }
    list_add(&page->lru,
                   &zone->free_area.free_list);
out:
    zone->free_area.nr_free++;
}

nswcfd 发表于 2016-03-08 20:20

3. 使用 main() 函数的构造函数作为 Uboot,使用 main() 作为 kernel 空间.
这句话怎么理解?

Buddy_Zhang1 发表于 2016-03-08 22:07

本帖最后由 Buddy_Zhang1 于 2016-03-08 22:10 编辑

回复 9# nswcfd


    就是 C 语言中 main() 函数的构造函数,main() 函数有它的构造函数和析构函数,我把构造函数当做 uboot 过程,把析构函数当做关机过程.
    该方法已经实现.
{:yxh45:}

    具体实现方法如下:


/*
* Simulate U-boot
*/
__attribute__((constructor)) __uboot U_boot(void)
{
        mm_debug("[%s]Boot From U_Boot\n",__FUNCTION__);
        u_boot_start();
        mm_debug("[%s]Uboot finish,start kernel...\n",__FUNCTION__);
        start_kernel();
        mm_debug("Kernel Running.....\n=====Hello World=====\n");
}
/*
* Simulate power-down.
*/
__attribute__((destructor)) __exit Pown_down(void)
{
        mm_debug("=======Goodbye=======\n");
        mm_debug("[%s]Pown down......\n",__func__);
}
页: [1] 2 3 4
查看完整版本: [73%]正在写一个模拟 Linux 内存管理的系统