memblock算法是linux内核初始化阶段的一个内存分配器(它取代了原来的bootmem算法),实现较为简单。负责page allocator初始化之前的内存管理和分配请求。

&nbsp; &nbsp;&nbsp;分析<span style="-ms-word-wrap: break-word;">memblock</span>算法,可以从几点入手:

1、 memblock算法初始化;

2、 memblock算法管理内存的申请和释放;
<span style="line-height: 1.5; -ms-word-wrap: break-word;">&nbsp; &nbsp;&nbsp;memblock算法前的准备:</span>

&nbsp; &nbsp;&nbsp;前面已经分析了<span style="-ms-word-wrap: break-word;">linux</span>系统在初始化的过程中,使用<span style="-ms-word-wrap: break-word;">int 15</span>中断探知了机器的内存分布图(<span style="-ms-word-wrap: break-word;">e820</span>图),其数据是存储在<span style="-ms-word-wrap: break-word;">boot_params.e820_map</span>里面,这里面是没有经过整理的数据,杂乱无章,毕竟<span style="-ms-word-wrap: break-word;">BIOS</span>没有责任做整理内存的事情,所以这部分事情由系统来实现。那么看一下<span style="-ms-word-wrap: break-word;">linux</span>如何实现这部分功能的,这部分功能是在<span style="-ms-word-wrap: break-word;">setup_memory_map</span>里面实现的。

&nbsp; &nbsp;&nbsp;该函数在初始化中的调用位置:

start_kernel()

└<span style="-ms-word-wrap: break-word;">-&gt;setup_arch()</span>


└<span style="-ms-word-wrap: break-word;">-&gt;setup_memory_map();</span>
&nbsp; &nbsp;&nbsp;函数实现:

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. void __init setup_memory_map(void)
3. {
4.     char *who;
5.  
6.     who = x86_init.resources.memory_setup();
7.     memcpy(&e820_saved, &e820, sizeof(struct e820map));
8.     printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n");
9.     e820_print_map(who);
10. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;可以看到实现很简单,先是调用了一个钩子函数,然后将</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">e820</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">保存到</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">e820_saved</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">里面,再往下就是</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">print</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">函数。很明显可以看到关键点在于这个钩子函数的实现,在</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">x86_init.c</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">里面可以找到</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">x86_init</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">该结构体变量的定义:</span>

&nbsp;

&nbsp;


1. 【file:/arch/x86/kernel/x86_init.c】
2. /
3.   The platform setup functions are preset with the default functions
4.   for standard PC hardware.
5.  /
6. struct x86_init_ops x86_init __initdata = {
7.  
8.     .resources = {
9.         .probe_roms = probe_roms,
10.         .reserve_resources = reserve_standard_io_resources,
11.         .memory_setup = default_machine_specific_memory_setup,
12.     },
13.  
14.     .mpparse = {
15.         .mpc_record = x86_init_uint_noop,
16.         .setup_ioapic_ids = x86_init_noop,
17.         .mpc_apic_id = default_mpc_apic_id,
18.         .smp_read_mpc_oem = default_smp_read_mpc_oem,
19.         .mpc_oem_bus_info = default_mpc_oem_bus_info,
20.         .find_smp_config = default_find_smp_config,
21.         .get_smp_config = default_get_smp_config,
22.     },
23.  
24.     .irqs = {
25.         .pre_vector_init = init_ISA_irqs,
26.         .intr_init = native_init_IRQ,
27.         .trap_init = x86_init_noop,
28.     },
29.  
30.     .oem = {
31.         .arch_setup = x86_init_noop,
32.         .banner = default_banner,
33.     },
34.  
35.     .paging = {
36.         .pagetable_init = native_pagetable_init,
37.     },
38.  
39.     .timers = {
40.         .setup_percpu_clockev = setup_boot_APIC_clock,
41.         .tsc_pre_init = x86_init_noop,
42.         .timer_init = hpet_time_init,
43.         .wallclock_init = x86_init_noop,
44.     },
45.  
46.     .iommu = {
47.         .iommu_init = iommu_init_noop,
48.     },
49.  
50.     .pci = {
51.         .init = x86_default_pci_init,
52.         .init_irq = x86_default_pci_init_irq,
53.         .fixup_irqs = x86_default_pci_fixup_irqs,
54.     },
55. };
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;由此可以看到该钩子函数挂的是</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">default_machine_specific_memory_setup()</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">。</span>

&nbsp;

&nbsp; &nbsp;&nbsp;进一步看一下该函数的实现:

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. char __init default_machine_specific_memory_setup(void)
3. {
4.     char who = "BIOS-e820";
5.     u32 new_nr;
6.     /
7.       Try to copy the BIOS-supplied E820-map.
8.      
9.       Otherwise fake a memory map; one section from 0k->640k,
10.       the next section from 1mb->appropriate_mem_k
11.      /
12.     new_nr = boot_params.e820_entries;
13.     sanitize_e820_map(boot_params.e820_map,
14.             ARRAY_SIZE(boot_params.e820_map),
15.             &new_nr);
16.     boot_params.e820_entries = new_nr;
17.     if (append_e820_map(boot_params.e820_map, boot_params.e820_entries)
18.       < 0) {
19.         u64 mem_size;
20.  
21.         / compare results from other methods and take the greater /
22.         if (boot_params.alt_mem_k
23.             < boot_params.screen_info.ext_mem_k) {
24.             mem_size = boot_params.screen_info.ext_mem_k;
25.             who = "BIOS-88";
26.         } else {
27.             mem_size = boot_params.alt_mem_k;
28.             who = "BIOS-e801";
29.         }
30.  
31.         e820.nr_map = 0;
32.         e820_add_region(0, LOWMEMSIZE(), E820_RAM);
33.         e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
34.     }
35.  
36.     / In case someone cares... /
37.     return who;
38. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;在这个函数里面,可以看到前面探测到的内存布局信息</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">boot_params.e820_map</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">在这里被使用了。</span>

&nbsp;

&nbsp; &nbsp;&nbsp;首先分析一下<span style="-ms-word-wrap: break-word;">sanitize_e820_map</span>该函数把<span style="-ms-word-wrap: break-word;">e820</span>信息进行了如何处理,函数实现:

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. int init sanitize_e820_map(struct e820entry biosmap, int max_nr_map,
3.                  u32 pnr_map)
4. {
5.     static struct change_member change_point_list[2*E820_X_MAX]
initdata;
6.     static struct change_member change_point[2E820_X_MAX] initdata;
7.     static struct e820entry *overlap_list[E820_X_MAX]
initdata;
8.     static struct e820entry new_bios[E820_X_MAX] __initdata;
9.     unsigned long current_type, last_type;
10.     unsigned long long last_addr;
11.     int chgidx;
12.     int overlap_entries;
13.     int new_bios_entry;
14.     int old_nr, new_nr, chg_nr;
15.     int i;
16.  
17.     / if there's only one memory region, don't bother /
18.     if (pnr_map < 2)
19.         return -1;
20.  
21.     old_nr = pnr_map;
22.     BUG_ON(old_nr > max_nr_map);
23.  
24.     / bail out if we find any unreasonable addresses in bios map /
25.     for (i = 0; i < old_nr; i++)
26.         if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
27.             return -1;
28.  
29.     / create pointers for initial change-point information (for sorting) /
30.     for (i = 0; i < 2 old_nr; i++)
31.         change_point[i] = &change_point_list[i];
32.  
33.     / record all known change-points (starting and ending addresses),
34.        omitting those that are for empty memory regions /
35.     chgidx = 0;
36.     for (i = 0; i < old_nr; i++) {
37.         if (biosmap[i].size != 0) {
38.             change_point[chgidx]->addr = biosmap[i].addr;
39.             change_point[chgidx++]->pbios = &biosmap[i];
40.             change_point[chgidx]->addr = biosmap[i].addr +
41.                 biosmap[i].size;
42.             change_point[chgidx++]->pbios = &biosmap[i];
43.         }
44.     }
45.     chg_nr = chgidx;
46.  
47.     / sort change-point list by memory addresses (low -> high) /
48.     sort(change_point, chg_nr, sizeof change_point, cpcompare, NULL);
49.  
50.     / create a new bios memory map, removing overlaps /
51.     overlap_entries = 0; / number of entries in the overlap table /
52.     new_bios_entry = 0; / index for creating new bios map entries /
53.     last_type = 0; / start with undefined memory type /
54.     last_addr = 0; / start with 0 as last starting address /
55.  
56.     / loop through change-points, determining affect on the new bios map /
57.     for (chgidx = 0; chgidx < chg_nr; chgidx++) {
58.         / keep track of all overlapping bios entries /
59.         if (change_point[chgidx]->addr ==
60.             change_point[chgidx]->pbios->addr) {
61.             /
62.               add map entry to overlap list (> 1 entry
63.               implies an overlap)
64.              /
65.             overlap_list[overlap_entries++] =
66.                 change_point[chgidx]->pbios;
67.         } else {
68.             /
69.               remove entry from list (order independent,
70.               so swap with last)
71.              /
72.             for (i = 0; i < overlap_entries; i++) {
73.                 if (overlap_list[i] ==
74.                     change_point[chgidx]->pbios)
75.                     overlap_list[i] =
76.                         overlap_list[overlap_entries-1];
77.             }
78.             overlap_entries--;
79.         }
80.         /
81.           if there are overlapping entries, decide which
82.           "type" to use (larger value takes precedence --
83.           1=usable, 2,3,4,4+=unusable)
84.          /
85.         current_type = 0;
86.         for (i = 0; i < overlap_entries; i++)
87.             if (overlap_list[i]->type > current_type)
88.                 current_type = overlap_list[i]->type;
89.         /
90.           continue building up new bios map based on this
91.           information
92.          /
93.         if (current_type != last_type) {
94.             if (last_type != 0) {
95.                 new_bios[new_bios_entry].size =
96.                     change_point[chgidx]->addr - last_addr;
97.                 /
98.                   move forward only if the new size
99.                   was non-zero
100.                  /
101.                 if (new_bios[new_bios_entry].size != 0)
102.                     /
103.                       no more space left for new
104.                       bios entries ?
105.                      /
106.                     if (++new_bios_entry >= max_nr_map)
107.                         break;
108.             }
109.             if (current_type != 0) {
110.                 new_bios[new_bios_entry].addr =
111.                     change_point[chgidx]->addr;
112.                 new_bios[new_bios_entry].type = current_type;
113.                 last_addr = change_point[chgidx]->addr;
114.             }
115.             last_type = current_type;
116.         }
117.     }
118.     / retain count for new bios entries /
119.     new_nr = new_bios_entry;
120.  
121.     / copy new bios mapping into original location /
122.     memcpy(biosmap, new_bios, new_nr sizeof(struct e820entry));
123.     *pnr_map = new_nr;
124.  
125.     return 0;
126. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;第一个</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">for</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">循环:</span>

&nbsp;

    / bail out if we find any unreasonable addresses in bios map /

&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; old_nr; i++)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;
&nbsp; &nbsp;&nbsp;这里是将<span style="-ms-word-wrap: break-word;">e820</span>做一个全面检测,检测是否存在不合理的内存布局信息项,存在不合理项则直接退出。

&nbsp; &nbsp;&nbsp;第二个<span style="-ms-word-wrap: break-word;">for</span>循环:

    / create pointers for initial change-point information (for sorting) /

&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; 2 * old_nr; i++)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[i] = &amp;change_point_list[i];
&nbsp; &nbsp;&nbsp;将<span style="-ms-word-wrap: break-word;">change_point</span>和<span style="-ms-word-wrap: break-word;">change_point_list</span>关联起来,实际上<span style="-ms-word-wrap: break-word;">change_point_list</span>只是占用一个栈空间而已,真正起到作用的是<span style="-ms-word-wrap: break-word;">change_point</span>。

&nbsp; &nbsp;&nbsp;第三个<span style="-ms-word-wrap: break-word;">for</span>循环和<span style="-ms-word-wrap: break-word;">sort</span>函数的调用一起来分析:

    /* record all known change-points (starting and ending addresses),

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; omitting those that are for empty memory regions */


&nbsp;&nbsp;&nbsp; chgidx = 0;


&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; old_nr; i++)&nbsp;&nbsp;&nbsp; {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (biosmap[i].size != 0) {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx]->addr = biosmap[i].addr;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx++]->pbios = &amp;biosmap[i];


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx]->addr = biosmap[i].addr +


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; biosmap[i].size;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx++]->pbios = &amp;biosmap[i];


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp; chg_nr = chgidx;


&nbsp;


&nbsp;&nbsp;&nbsp; /* sort change-point list by memory addresses (low -&gt; high) */


&nbsp;&nbsp;&nbsp; sort(change_point, chg_nr, sizeof *change_point, cpcompare, NULL);
&nbsp; &nbsp;&nbsp;这里是把<span style="-ms-word-wrap: break-word;">change_point</span>初始化并与<span style="-ms-word-wrap: break-word;">boot_params.e820_map</span>各项的起始地址和结束地址分别关联起来,继而通过<span style="-ms-word-wrap: break-word;">sort</span>来进行排序。排序的结果就是将各项内存布局信息所标示的内存空间起始地址和结束地址由低往高进行排序。如果两者地址值相等,则以两者的<span style="-ms-word-wrap: break-word;">e820_map</span>项信息所标示的内存空间尾做排序依据,哪个空间尾更后,则该项排在等值项后面。

&nbsp; &nbsp;&nbsp;看一下最后的<span style="-ms-word-wrap: break-word;">for</span>循环:

    / loop through change-points, determining affect on the new bios map /

&nbsp;&nbsp;&nbsp; for (chgidx = 0; chgidx &lt; chg_nr; chgidx++) {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* keep track of all overlapping bios entries */


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (change_point[chgidx]-&gt;addr ==


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; change_point[chgidx]-&gt;pbios-&gt;addr) {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* add map entry to overlap list (&gt; 1 entry


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* implies an overlap)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overlap_list[overlap_entries++] =


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx]-&gt;pbios;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* remove entry from list (order independent,


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* so swap with last)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; overlap_entries; i++) {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (overlap_list[i] ==


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; change_point[chgidx]-&gt;pbios)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overlap_list[i] =


&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overlap_list[overlap_entries-1];


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overlap_entries--;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* if there are overlapping entries, decide which


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* &quot;type&quot; to use (larger value takes precedence --


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* 1=usable, 2,3,4,4+=unusable)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current_type = 0;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; overlap_entries; i++)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (overlap_list[i]-&gt;type &gt; current_type)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current_type = overlap_list[i]-&gt;type;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* continue building up new bios map based on this


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* information


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (current_type != last_type)&nbsp; {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (last_type != 0) {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new_bios[new_bios_entry].size =


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx]-&gt;addr - last_addr;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* move forward only if the new size


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* was non-zero


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (new_bios[new_bios_entry].size != 0)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* no more space left for new


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;* bios entries ?


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;*/


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (++new_bios_entry &gt;= max_nr_map)


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (current_type != 0)&nbsp; {


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new_bios[new_bios_entry].addr =


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; change_point[chgidx]-&gt;addr;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new_bios[new_bios_entry].type = current_type;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_addr = change_point[chgidx]-&gt;addr;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_type = current_type;


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }


&nbsp;&nbsp;&nbsp; }
&nbsp; &nbsp;&nbsp;这个循环里面干了什么事情呢?其大概作用就是把已经排序完了的<span style="-ms-word-wrap: break-word;">change_point</span>做整合,将重叠的内存空间根据属性进行筛选,并将同属性的相邻内存空间进行合并处理。具体实现流程为:

&nbsp; &nbsp;&nbsp;1、 最初第一次循环加入<span style="-ms-word-wrap: break-word;">change_point</span>项,将根据当前<span style="-ms-word-wrap: break-word;">change_point</span>记录的地址项是否与其关联的<span style="-ms-word-wrap: break-word;">e820_map</span>项的起始地址一致,如果一致(第一次必然是一致的),表示当前项是某内存块的起始地址,将其加入到<span style="-ms-word-wrap: break-word;">overlap_list</span>中去,然后该项将会添加到<span style="-ms-word-wrap: break-word;">new_bios</span>中并更新<span style="-ms-word-wrap: break-word;">last_addr</span>,最后更新当前内存块的内存类型到<span style="-ms-word-wrap: break-word;">last_type</span>中(这个类型当做优先级理解,会容易理解代码的,<span style="-ms-word-wrap: break-word;">0</span>优先级最低);

&nbsp; &nbsp;&nbsp;2、 第二次循环加入<span style="-ms-word-wrap: break-word;">change_point</span>项,就会开始遇到各种状况了:

&nbsp; &nbsp;&nbsp;A.&nbsp;&nbsp; 假设<span style="-ms-word-wrap: break-word;">change_point</span>新加入项是第一项的内存尾,那么<span style="-ms-word-wrap: break-word;">overlap_list</span>将会移除该项,<span style="-ms-word-wrap: break-word;">new_bios</span>将会更新当前项的内存块大小,只要内存块大小不为<span style="-ms-word-wrap: break-word;">0</span>,那么<span style="-ms-word-wrap: break-word;">new_bios_entry</span>自加,<span style="-ms-word-wrap: break-word;">new_bios</span>开始新一项的内容记录;

&nbsp; &nbsp;&nbsp;B.&nbsp;&nbsp; 假设<span style="-ms-word-wrap: break-word;">change_point</span>新加入项是新的内存块地址头,那么<span style="-ms-word-wrap: break-word;">overlap_list</span>将会新增一项,然后<span style="-ms-word-wrap: break-word;">current_type</span>将会更新到<span style="-ms-word-wrap: break-word;">overlap_list</span>列表中的所有项的类型最大值(最高优先级),接下来又出现新状况了:

&nbsp; &nbsp;&nbsp;a)&nbsp;&nbsp; 如果当前新加入<span style="-ms-word-wrap: break-word;">change_point</span>的类型值等于前者,继续开始下一循环;

&nbsp; &nbsp;&nbsp;b)&nbsp;&nbsp; 如果当前新加入<span style="-ms-word-wrap: break-word;">change_point</span>的类型值大于前者,那么<span style="-ms-word-wrap: break-word;">new_bios</span>将会以该<span style="-ms-word-wrap: break-word;">change_point</span>项纪录的地址作为<span style="-ms-word-wrap: break-word;">new_bios</span>前一项的结束地址,然后更新大小到<span style="-ms-word-wrap: break-word;">new_bios</span>中,开启<span style="-ms-word-wrap: break-word;">new_bios</span>的新一项的记录;

&nbsp; &nbsp;&nbsp;c)&nbsp;&nbsp; 如果当前新加入<span style="-ms-word-wrap: break-word;">change_point</span>的类型值小于前者,由于<span style="-ms-word-wrap: break-word;">current_type</span>将会仍然保持前者的类型值,后续将会跳过开始下一循环;

&nbsp; &nbsp;&nbsp;3、 第三次循环加入<span style="-ms-word-wrap: break-word;">change_point</span>项,基于前面第二次循环加入<span style="-ms-word-wrap: break-word;">change_point</span>项的情况,如果是情况<span style="-ms-word-wrap: break-word;">A</span>,那么问题很简单,就是一个新开始而已;如果是情况<span style="-ms-word-wrap: break-word;">B</span>,将会出现稍微复杂的情况:

&nbsp; &nbsp;&nbsp;A.&nbsp;&nbsp; 假设该<span style="-ms-word-wrap: break-word;">change_point</span>新加入项又是新的内存块头,将会涉及类型值不同的问题,其实也就是重复前面类型第二次循环的情况<span style="-ms-word-wrap: break-word;">B</span>的场景,这里就不细述了;

&nbsp; &nbsp;&nbsp;B.&nbsp;&nbsp; 假设该<span style="-ms-word-wrap: break-word;">change_point</span>新加入项是前面的内存块尾,那么可能的状况是:

&nbsp; &nbsp;&nbsp;a)&nbsp;&nbsp; 如果前面已加入的两项类型相同,即<span style="-ms-word-wrap: break-word;">B.a</span>的情形,当前作为内存尾新加入<span style="-ms-word-wrap: break-word;">change_point</span>的类型值必然也是相同的,这仅会把与<span style="-ms-word-wrap: break-word;">overlap_list</span>中配对的那一项从队列中删除,继续开始加入<span style="-ms-word-wrap: break-word;">change_point</span>下一项;

&nbsp; &nbsp;&nbsp;b)&nbsp;&nbsp; 如果前面两项,第一项类型值大于第二项,即<span style="-ms-word-wrap: break-word;">B.c</span>的情形,若当前项作为第一项的尾加入,那么当前的<span style="-ms-word-wrap: break-word;">new_bios</span>项将会以此作为结尾;但是若当前项作为第二项的尾加入,那么将把第二项从<span style="-ms-word-wrap: break-word;">overlap_list</span>中删除;

&nbsp; &nbsp;&nbsp;c)&nbsp;&nbsp; 如果前面两项,第二项类型值大于第一项,即<span style="-ms-word-wrap: break-word;">B.b</span>的情形,若当前项作为第一项的尾加入,也仅是将第一项从<span style="-ms-word-wrap: break-word;">overlap_list</span>中删除;若当前项作为第一项的尾加入,那么<span style="-ms-word-wrap: break-word;">new_bios</span>将会就此作为尾完成当前项;

&nbsp; &nbsp;&nbsp;后续的循环加入<span style="-ms-word-wrap: break-word;">change_point</span>项也仅是前面的场景演变而已,这里不细述了。那么从前面的信息来看,这个函数的目的是什么基本明了,也就是将<span style="-ms-word-wrap: break-word;">boot_params.e820_map</span>里面的内存布局根据顺序和重叠情况,将连续的同类型的内存块合并,将不同类型的内存块根据高低优先级进行内存块划分拆开。

&nbsp; &nbsp;&nbsp;正如下描述的一样:

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. /
3.   Sanitize the BIOS e820 map.
4.  
5.   Some e820 responses include overlapping entries. The following
6.   replaces the original e820 map with a new one, removing overlaps,
7.   and resolving conflicting memory types in favor of highest
8.   numbered type.
9.  
10.   The input parameter biosmap points to an array of 'struct
11.   e820entry' which on entry has elements in the range [0, pnr_map)
12.   valid, and which has space for up to max_nr_map entries.
13.   On return, the resulting sanitized e820 map entries will be in
14.   overwritten in the same location, starting at biosmap.
15.  
16.   The integer pointed to by pnr_map must be valid on entry (the
17.   current number of valid entries located at biosmap) and will
18.   be updated on return, with the new number of valid entries
19.   (something no more than max_nr_map.)
20.  
21.   The return value from sanitize_e820_map() is zero if it
22.   successfully 'sanitized' the map entries passed in, and is -1
23.   if it did nothing, which can happen if either of (1) it was
24.   only passed one map entry, or (2) any of the input map entries
25.   were invalid (start + size < start, meaning that the size was
26.   so big the described memory range wrapped around through zero.)
27.  
28.   Visually we're performing the following
29.   (1,2,3,4 = memory types)...
30.  
31.   Sample memory map (w/overlaps):
32.   22__
33.   __4_
34.   1111__
35.   44__
36.   11111111__
37.   __33__
38.   ___44___
39.   __33333_
40.   __22__
41.   ___2222_
42.   _111111111__
43.   _11_
44.   _4__
45.  
46.   Sanitized equivalent (no overlap):
47.   1___
48.   44__
49.   _1__
50.   22__
51.   __11__
52.   _1__
53.   __3_
54.   ___44___
55.   _33_
56.   ___2__
57.   __1___
58.   _4__
59.   ___2__
60.   __33
61.  * __
4_
62.  */
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;为了方便理解,整理出一张草图:</span>

&nbsp;

&nbsp;

&nbsp; &nbsp;&nbsp;连续的同类型的合并到一块里面,不同类型的各自为政,不同类型重叠部分根据类型优先级高低拆分,依高优先级顺序保证各类型的内存块的完整性。额外废话一句:目前玩虚拟机没有遇到过上面这么复杂的情况,但是不能否认这段代码是设计来干这活的。

&nbsp; &nbsp;&nbsp;从<span style="-ms-word-wrap: break-word;">sanitize_e820_map</span>出来后,回到<span style="-ms-word-wrap: break-word;">default_machine_specific_memory_setup</span>中,接下来是<span style="-ms-word-wrap: break-word;">append_e820_map</span>的函数:

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. static int init append_e820_map(struct e820entry biosmap, int nr_map)
3. {
4.     / Only one memory region (or negative)? Ignore it */
5.     if (nr_map < 2)
6.         return -1;
7.  
8.     return
append_e820_map(biosmap, nr_map);
9. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;append_e820_map封装调用</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">__append_e820_map</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">:</span>

&nbsp;

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. static int init append_e820_map(struct e820entry biosmap, int nr_map)
3. {
4.     while (nr_map) {
5.         u64 start = biosmap->addr;
6.         u64 size = biosmap->size;
7.         u64 end = start + size;
8.         u32 type = biosmap->type;
9.  
10.         / Overflow in 64 bits? Ignore the memory map. */
11.         if (start > end)
12.             return -1;
13.  
14.         e820_add_region(start, size, type);
15.  
16.         biosmap++;
17.         nr_map--;
18.     }
19.     return 0;
20. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;循环调用</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">e820_add_region</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">将整理后的</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">boot_params.e820_map</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">做添加操作:</span>

&nbsp;

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. void init e820_add_region(u64 start, u64 size, int type)
3. {
4.     
e820_add_region(&e820, start, size, type);
5. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;e820_add_region封装</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">__e820_add_region</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">:</span>

&nbsp;

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. static void init e820_add_region(struct e820map *e820x, u64 start, u64 size,
3.                      int type)
4. {
5.     int x = e820x->nr_map;
6.  
7.     if (x >= ARRAY_SIZE(e820x->map)) {
8.         printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n",
9.                (unsigned long long) start,
10.                (unsigned long long) (start + size - 1));
11.         return;
12.     }
13.  
14.     e820x->map[x].addr = start;
15.     e820x->map[x].size = size;
16.     e820x->map[x].type = type;
17.     e820x->nr_map++;
18. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;而</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">__e820_add_region</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">则是将各项信息往</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">e820</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">做添加操作。说白了,就是将</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">boot_params.e820_map</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">转入到</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">e820</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">图中。</span>

&nbsp;

&nbsp; &nbsp;&nbsp;最后顺便看一下<span style="-ms-word-wrap: break-word;">e820_print_map</span>函数的实现:

&nbsp;


1. 【file:/arch/x86/kernel/e820.c】
2. void __init e820_print_map(char *who)
3. {
4.     int i;
5.  
6.     for (i = 0; i < e820.nr_map; i++) {
7.         printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who,
8.                (unsigned long long) e820.map[i].addr,
9.                (unsigned long long)
10.                (e820.map[i].addr + e820.map[i].size - 1));
11.         e820_print_type(e820.map[i].type);
12.         printk(KERN_CONT "\n");
13.     }
14. }
<span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">&nbsp; &nbsp;&nbsp;它是将钩子函数返回的内容打印出来,打印出来的内容可以在</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">shell</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">上面通过</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; white-space: normal; -ms-word-wrap: break-word; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">dmesg</span><span style="text-align: left; color: rgb(102, 102, 102); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: 宋体, Arial; font-size: 16px; font-style: normal; font-weight: normal; word-spacing: 0px; float: none; display: inline !important; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;">命令查看得到,例如:</span>

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp; &nbsp;&nbsp;最后总结一下,以上代码干了这么多活,主要就是为了把通过<span style="-ms-word-wrap: break-word;">BIOS</span>中断探测到的内存布局信息<span style="-ms-word-wrap: break-word;">boot_params.e820_map</span>做整合处理,完了转存到变量<span style="-ms-word-wrap: break-word;">e820</span>中。

[http://blog.chinaunix.net/uid-26859697-id-4498257.html](http://blog.chinaunix.net/uid-26859697-id-4498257.html)