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的专栏

相关内容

    暂无相关文章