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

linux內存管理之活動內存區

日期:2017/3/1 17:23:08   编辑:關於Linux
Linux內存活動區域其實就是全局變量e820中的內存塊做了相關的檢查和對其處理後的區域。在管理區初始化等地方有用到。

數據結構


struct node_active_region {
unsigned long start_pfn;
unsigned long end_pfn;
int nid;
};
初始化

活動內存的初始化工作在setup_arch()->initmem_init()->e820_register_active_regions()中


/* Walk the e820 map and register active regions within a node */
void __init e820_register_active_regions(int nid, unsigned long start_pfn,
unsigned long last_pfn)
{
unsigned long ei_startpfn;
unsigned long ei_endpfn;
int i;

for (i = 0; i < e820.nr_map; i++)
if (e820_find_active_region(&e820.map[i],/*從全局變量e820中查找活動區*/
start_pfn, last_pfn,
&ei_startpfn, &ei_endpfn))
add_active_range(nid, ei_startpfn, ei_endpfn);/*加入活動區*/
}

/*
* Finds an active region in the address range from start_pfn to last_pfn and
* returns its range in ei_startpfn and ei_endpfn for the e820 entry.
*/
int __init e820_find_active_region(const struct e820entry *ei,
unsigned long start_pfn,
unsigned long last_pfn,
unsigned long *ei_startpfn,
unsigned long *ei_endpfn)
{
u64 align = PAGE_SIZE;

*ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
*ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;

/* Skip map entries smaller than a page */
if (*ei_startpfn >= *ei_endpfn)
return 0;

/* Skip if map is outside the node */
if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
*ei_startpfn >= last_pfn)
return 0;

/* Check for overlaps */
if (*ei_startpfn < start_pfn)
*ei_startpfn = start_pfn;
if (*ei_endpfn > last_pfn)
*ei_endpfn = last_pfn;

return 1;
}

/*添加活動區域,需要對原有的進行檢查*/
void __init add_active_range(unsigned int nid, unsigned long start_pfn,
unsigned long end_pfn)
{
int i;

mminit_dprintk(MMINIT_TRACE, "memory_register",
"Entering add_active_range(%d, %#lx, %#lx) "
"%d entries of %d used\n",
nid, start_pfn, end_pfn,
nr_nodemap_entries, MAX_ACTIVE_REGIONS);
//not set macro
mminit_validate_memmodel_limits(&start_pfn, &end_pfn);

/* Merge with existing active regions if possible */
for (i = 0; i < nr_nodemap_entries; i++) {
if (early_node_map[i].nid != nid)
continue;

/* Skip if an existing region covers this new one */
if (start_pfn >= early_node_map[i].start_pfn &&
end_pfn <= early_node_map[i].end_pfn)
return;

/* Merge forward if suitable */
if (start_pfn <= early_node_map[i].end_pfn &&
end_pfn > early_node_map[i].end_pfn) {
early_node_map[i].end_pfn = end_pfn;
return;
}

/* Merge backward if suitable */
if (start_pfn < early_node_map[i].end_pfn &&
end_pfn >= early_node_map[i].start_pfn) {
early_node_map[i].start_pfn = start_pfn;
return;
}
}

/* Check that early_node_map is large enough */
if (i >= MAX_ACTIVE_REGIONS) {
printk(KERN_CRIT "More than %d memory regions, truncating\n",
MAX_ACTIVE_REGIONS);
return;
}

early_node_map[i].nid = nid;
early_node_map[i].start_pfn = start_pfn;
early_node_map[i].end_pfn = end_pfn;
nr_nodemap_entries = i + 1;
}

摘自 bullbat的專欄
Copyright © Linux教程網 All Rights Reserved