Linux内存管理之活动内存区


Linux内存活动区域其实就是全局变量e820中的内存块做了相关的检查和对其处理后的区域。在管理区初始化等地方有用到。

数据结构

  1. struct node_active_region {  
  2.     unsigned long start_pfn;  
  3.     unsigned long end_pfn;  
  4.     int nid;  
  5. };  

初始化

活动内存的初始化工作在setup_arch()->initmem_init()->e820_register_active_regions()

  1. /* Walk the e820 map and register active regions within a node */  
  2. void __init e820_register_active_regions(int nid, unsigned long start_pfn,  
  3.                      unsigned long last_pfn)  
  4. {  
  5.     unsigned long ei_startpfn;  
  6.     unsigned long ei_endpfn;  
  7.     int i;  
  8.   
  9.     for (i = 0; i < e820.nr_map; i++)  
  10.         if (e820_find_active_region(&e820.map[i],/*从全局变量e820中查找活动区*/  
  11.                         start_pfn, last_pfn,  
  12.                         &ei_startpfn, &ei_endpfn))  
  13.             add_active_range(nid, ei_startpfn, ei_endpfn);/*加入活动区*/  
  14. }  
 
  1. /* 
  2.  * Finds an active region in the address range from start_pfn to last_pfn and 
  3.  * returns its range in ei_startpfn and ei_endpfn for the e820 entry. 
  4.  */  
  5. int __init e820_find_active_region(const struct e820entry *ei,  
  6.                   unsigned long start_pfn,  
  7.                   unsigned long last_pfn,  
  8.                   unsigned long *ei_startpfn,  
  9.                   unsigned long *ei_endpfn)  
  10. {  
  11.     u64 align = PAGE_SIZE;  
  12.   
  13.     *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;  
  14.     *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;  
  15.   
  16.     /* Skip map entries smaller than a page */  
  17.     if (*ei_startpfn >= *ei_endpfn)  
  18.         return 0;  
  19.   
  20.     /* Skip if map is outside the node */  
  21.     if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||  
  22.                     *ei_startpfn >= last_pfn)  
  23.         return 0;  
  24.   
  25.     /* Check for overlaps */  
  26.     if (*ei_startpfn < start_pfn)  
  27.         *ei_startpfn = start_pfn;  
  28.     if (*ei_endpfn > last_pfn)  
  29.         *ei_endpfn = last_pfn;  
  30.   
  31.     return 1;  
  32. }  
 
  1. /*添加活动区域,需要对原有的进行检查*/  
  2. void __init add_active_range(unsigned int nid, unsigned long start_pfn,  
  3.                         unsigned long end_pfn)  
  4. {  
  5.     int i;  
  6.   
  7.     mminit_dprintk(MMINIT_TRACE, "memory_register",  
  8.             "Entering add_active_range(%d, %#lx, %#lx) "  
  9.             "%d entries of %d used\n",  
  10.             nid, start_pfn, end_pfn,  
  11.             nr_nodemap_entries, MAX_ACTIVE_REGIONS);  
  12. //not set macro   
  13.     mminit_validate_memmodel_limits(&start_pfn, &end_pfn);  
  14.   
  15.     /* Merge with existing active regions if possible */  
  16.     for (i = 0; i < nr_nodemap_entries; i++) {  
  17.         if (early_node_map[i].nid != nid)  
  18.             continue;  
  19.   
  20.         /* Skip if an existing region covers this new one */  
  21.         if (start_pfn >= early_node_map[i].start_pfn &&  
  22.                 end_pfn <= early_node_map[i].end_pfn)  
  23.             return;  
  24.   
  25.         /* Merge forward if suitable */  
  26.         if (start_pfn <= early_node_map[i].end_pfn &&  
  27.                 end_pfn > early_node_map[i].end_pfn) {  
  28.             early_node_map[i].end_pfn = end_pfn;  
  29.             return;  
  30.         }  
  31.   
  32.         /* Merge backward if suitable */  
  33.         if (start_pfn < early_node_map[i].end_pfn &&  
  34.                 end_pfn >= early_node_map[i].start_pfn) {  
  35.             early_node_map[i].start_pfn = start_pfn;  
  36.             return;  
  37.         }  
  38.     }  
  39.   
  40.     /* Check that early_node_map is large enough */  
  41.     if (i >= MAX_ACTIVE_REGIONS) {  
  42.         printk(KERN_CRIT "More than %d memory regions, truncating\n",  
  43.                             MAX_ACTIVE_REGIONS);  
  44.         return;  
  45.     }  
  46.   
  47.     early_node_map[i].nid = nid;  
  48.     early_node_map[i].start_pfn = start_pfn;  
  49.     early_node_map[i].end_pfn = end_pfn;  
  50.     nr_nodemap_entries = i + 1;  
  51. }  

相关内容