免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1282 | 回复: 1
打印 上一主题 下一主题

linux启动内存分配器 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-05 16:24 |只看该作者 |倒序浏览
linux启动内存分配器







linux启动内存分配器是在伙伴系统、slab机制实现之前,为满足内核中内存的分配而建立的。本身的机制比较简单,使用位图来进行标志分配和释放。

一、数据结构介绍

1,保留区间

因为在建立启动内存分配器的时候,会涉及保留内存。也就是说,之前保留给页表、分配器本身(用于映射的位图)、io等得内存在分配器建立后,当用它来分配内存空间时,保留出来的那些部分就不能再分配了。linux中对保留内存空间的部分用下列数据结构表示
  1. view plaincopy to clipboardprint?/*
  2. * Early reserved memory areas.
  3. */  
  4. #define MAX_EARLY_RES 20/*保留空间最大块数*/   
  5.   
  6. struct early_res {/*保留空间结构*/  
  7.     u64 start, end;  
  8.     char name[16];  
  9.     char overlap_ok;  
  10. };  
  11. /*保留内存空间全局变量*/  
  12. static struct early_res early_res[MAX_EARLY_RES] __initdata = {  
  13.     { 0, PAGE_SIZE, "BIOS data page" }, /* BIOS data page */  
  14.     {}  
  15. };  
  16. /*
  17. * Early reserved memory areas.
  18. */
  19. #define MAX_EARLY_RES 20/*保留空间最大块数*/

  20. struct early_res {/*保留空间结构*/
  21.         u64 start, end;
  22.         char name[16];
  23.         char overlap_ok;
  24. };
  25. /*保留内存空间全局变量*/
  26. static struct early_res early_res[MAX_EARLY_RES] __initdata = {
  27.         { 0, PAGE_SIZE, "BIOS data page" },        /* BIOS data page */
  28.         {}
  29. };2,bootmem分配器


  30. view plaincopy to clipboardprint?/*
  31. * node_bootmem_map is a map pointer - the bits represent all physical  
  32. * memory pages (including holes) on the node.
  33. */  
  34. /*用于bootmem分配器的节点数据结构*/  
  35. typedef struct bootmem_data {  
  36.     unsigned long node_min_pfn;/*存放bootmem位图的第一个页面(即内核映象结束处的第一个页面)。*/  
  37.     unsigned long node_low_pfn;/*物理内存的顶点,最高不超过896MB。*/  
  38.     void *node_bootmem_map;  
  39.     unsigned long last_end_off;/*用来存放在前一次分配中所分配的最后一个字节相对于last_pos的位移量*/  
  40.     unsigned long hint_idx;/*存放前一次分配的最后一个页面号*/  
  41.     struct list_head list;  
  42. } bootmem_data_t;  
  43. /*
  44. * node_bootmem_map is a map pointer - the bits represent all physical
  45. * memory pages (including holes) on the node.
  46. */
  47. /*用于bootmem分配器的节点数据结构*/
  48. typedef struct bootmem_data {
  49.         unsigned long node_min_pfn;/*存放bootmem位图的第一个页面(即内核映象结束处的第一个页面)。*/
  50.         unsigned long node_low_pfn;/*物理内存的顶点,最高不超过896MB。*/
  51.         void *node_bootmem_map;
  52.         unsigned long last_end_off;/*用来存放在前一次分配中所分配的最后一个字节相对于last_pos的位移量*/
  53.         unsigned long hint_idx;/*存放前一次分配的最后一个页面号*/
  54.         struct list_head list;
  55. } bootmem_data_t;
复制代码
全局链表
  1. view plaincopy to clipboardprint?static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);  
  2. static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);
复制代码
二、启动分配器的建立

启动分配器的建立主要的流程为初始化映射位图、活动内存区的映射位置0(表示可用)、保留内存区域处理,其中保留区存放在上面介绍的全局数组中,这里只是将分配器中对应映射位图值1,表示已经分配。

下面我们看内核中具体的初始化流程。
  1. start_kernel()->setup_arch()->initmem_init()


  2. view plaincopy to clipboardprint?void __init setup_arch(char **cmdline_p)  
  3. {  
  4.           .......  
  5. <span style="white-space: pre; "> </span>/*此函数在开始对bootmem分配制度建立做些准备工作  
  6.     然后调用相关函数建立bootmem分配制度*/  
  7.     initmem_init(0, max_pfn);  
  8.           .......  
  9. }            
  10. void __init setup_arch(char **cmdline_p)
  11. {
  12.           .......
  13. <span style="white-space: pre; ">        </span>/*此函数在开始对bootmem分配制度建立做些准备工作
  14.         然后调用相关函数建立bootmem分配制度*/
  15.         initmem_init(0, max_pfn);
  16.           .......
  17. }           
  18. view plaincopy to clipboardprint?<span style="font-family: Arial, Verdana, sans-serif; "><span style="white-space: normal; "></span></span>  
  19. <span style="font-family: Arial, Verdana, sans-serif; "><span style="white-space: normal; "></span></span>view plaincopy to clipboardprint?<span style="font-family: Arial, Verdana, sans-serif; "><span style="white-space: normal; "></span></span><pre name="code" class="cpp">void __init initmem_init(unsigned long start_pfn,  
  20.                   unsigned long end_pfn)  
  21. {  
  22. #ifdef CONFIG_HIGHMEM  
  23.     highstart_pfn = highend_pfn = max_pfn;  
  24.     if (max_pfn > max_low_pfn)  
  25.         highstart_pfn = max_low_pfn;  
  26.     /*将活动内存放到early_node_map中,前面已经分析过了*/  
  27.     e820_register_active_regions(0, 0, highend_pfn);  
  28.     /*设置上面变量中的内存为当前,在这里没有  
  29.     设置相关的宏*/  
  30.     sparse_memory_present_with_active_regions(0);  
  31.     printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",  
  32.         pages_to_mb(highend_pfn - highstart_pfn));  
  33.     num_physpages = highend_pfn;  
  34.     /*高端内存开始地址物理*/  
  35.     high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;  
  36. #else  
  37.     e820_register_active_regions(0, 0, max_low_pfn);  
  38.     sparse_memory_present_with_active_regions(0);  
  39.     num_physpages = max_low_pfn;  
  40.     high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;  
  41. #endif  
  42. #ifdef CONFIG_FLATMEM  
  43.     max_mapnr = num_physpages;  
  44. #endif  
  45.     __vmalloc_start_set = true;  
  46.   
  47.     printk(KERN_NOTICE "%ldMB LOWMEM available.\n",  
  48.             pages_to_mb(max_low_pfn));  
  49.     /*安装bootmem分配器,此分配器在伙伴系统起来之前  
  50.     用来进行承担内存的分配等管理*/  
  51.     setup_bootmem_allocator();  
  52. }  
  53. <span style="font-family: Arial, Verdana, sans-serif; "><span style="white-space: normal; "></span></span><pre name="code" class="cpp">void __init initmem_init(unsigned long start_pfn,
  54.                                   unsigned long end_pfn)
  55. {
  56. #ifdef CONFIG_HIGHMEM
  57.         highstart_pfn = highend_pfn = max_pfn;
  58.         if (max_pfn > max_low_pfn)
  59.                 highstart_pfn = max_low_pfn;
  60.         /*将活动内存放到early_node_map中,前面已经分析过了*/
  61.         e820_register_active_regions(0, 0, highend_pfn);
  62.         /*设置上面变量中的内存为当前,在这里没有
  63.         设置相关的宏*/
  64.         sparse_memory_present_with_active_regions(0);
  65.         printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
  66.                 pages_to_mb(highend_pfn - highstart_pfn));
  67.         num_physpages = highend_pfn;
  68.         /*高端内存开始地址物理*/
  69.         high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
  70. #else
  71.         e820_register_active_regions(0, 0, max_low_pfn);
  72.         sparse_memory_present_with_active_regions(0);
  73.         num_physpages = max_low_pfn;
  74.         high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
  75. #endif
  76. #ifdef CONFIG_FLATMEM
  77.         max_mapnr = num_physpages;
  78. #endif
  79.         __vmalloc_start_set = true;

  80.         printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
  81.                         pages_to_mb(max_low_pfn));
  82.         /*安装bootmem分配器,此分配器在伙伴系统起来之前
  83.         用来进行承担内存的分配等管理*/
  84.         setup_bootmem_allocator();
  85. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2012-01-05 16:25 |只看该作者
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP