歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux內存管理之活動內存區

Linux內存管理之活動內存區

日期:2017/2/28 16:00:22   编辑: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. for (i = 0; i < e820.nr_map; i++)
  9. if (e820_find_active_region(&e820.map[i],/*從全局變量e820中查找活動區*/
  10. start_pfn, last_pfn,
  11. &ei_startpfn, &ei_endpfn))
  12. add_active_range(nid, ei_startpfn, ei_endpfn);/*加入活動區*/
  13. }
  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. *ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
  13. *ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
  14. /* Skip map entries smaller than a page */
  15. if (*ei_startpfn >= *ei_endpfn)
  16. return 0;
  17. /* Skip if map is outside the node */
  18. if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
  19. *ei_startpfn >= last_pfn)
  20. return 0;
  21. /* Check for overlaps */
  22. if (*ei_startpfn < start_pfn)
  23. *ei_startpfn = start_pfn;
  24. if (*ei_endpfn > last_pfn)
  25. *ei_endpfn = last_pfn;
  26. return 1;
  27. }
  1. /*添加活動區域,需要對原有的進行檢查*/
  2. void __init add_active_range(unsigned int nid, unsigned long start_pfn,
  3. unsigned long end_pfn)
  4. {
  5. int i;
  6. mminit_dprintk(MMINIT_TRACE, "memory_register",
  7. "Entering add_active_range(%d, %#lx, %#lx) "
  8. "%d entries of %d used\n",
  9. nid, start_pfn, end_pfn,
  10. nr_nodemap_entries, MAX_ACTIVE_REGIONS);
  11. //not set macro
  12. mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
  13. /* Merge with existing active regions if possible */
  14. for (i = 0; i < nr_nodemap_entries; i++) {
  15. if (early_node_map[i].nid != nid)
  16. continue;
  17. /* Skip if an existing region covers this new one */
  18. if (start_pfn >= early_node_map[i].start_pfn &&
  19. end_pfn <= early_node_map[i].end_pfn)
  20. return;
  21. /* Merge forward if suitable */
  22. if (start_pfn <= early_node_map[i].end_pfn &&
  23. end_pfn > early_node_map[i].end_pfn) {
  24. early_node_map[i].end_pfn = end_pfn;
  25. return;
  26. }
  27. /* Merge backward if suitable */
  28. if (start_pfn < early_node_map[i].end_pfn &&
  29. end_pfn >= early_node_map[i].start_pfn) {
  30. early_node_map[i].start_pfn = start_pfn;
  31. return;
  32. }
  33. }
  34. /* Check that early_node_map is large enough */
  35. if (i >= MAX_ACTIVE_REGIONS) {
  36. printk(KERN_CRIT "More than %d memory regions, truncating\n",
  37. MAX_ACTIVE_REGIONS);
  38. return;
  39. }
  40. early_node_map[i].nid = nid;
  41. early_node_map[i].start_pfn = start_pfn;
  42. early_node_map[i].end_pfn = end_pfn;
  43. nr_nodemap_entries = i + 1;
  44. }
Copyright © Linux教程網 All Rights Reserved