设为首页 加入收藏

TOP

2. Linux-3.14.12内存管理笔记【系统启动阶段的memblock算法(2)】(一)
2019-09-24 18:10:44 】 浏览:123
Tags:Linux-3.14.12 内存 管理 笔记 系统 启动 阶段 memblock 算法

memory:表示可用可分配的内存;
结束完memblock算法初始化前的准备工作,回到memblock算法初始化及其算法实现上面。memblock是一个很简单的算法。

memblock算法的实现是,它将所有状态都保存在一个全局变量__initdata_memblock中,算法的初始化以及内存的申请释放都是在将内存块的状态做变更。那么从数据结构入手,

__initdata_memblock是一个memblock结构体。其结构体定义:

【file:/include/linux/memblock.h】
struct memblock {
    bool bottom_up; /* is bottom up direction? */
    phys_addr_t current_limit;
    struct memblock_type memory;
    struct memblock_type reserved;
};

结构体内各成员的意思:

  • bottom_up:用来表示分配器分配内存是自低地址(低地址指的是内核映像尾部,下同)向高地址还是自高地址向低地址来分配的;
  • current_limit:用来表示用来限制memblock_alloc()和memblock_alloc_base(..., MEMBLOCK_ALLOC_ACCESSIBLE)的内存申请;
  • memory:表示可用可分配的内存;
  • reserved:表示已经分配出去了的内存;

memory和reserved是很关键的一个数据结构,memblock算法的内存初始化和申请释放都是围绕着它们转。

往下看看memory和reserved的结构体memblock_type定义:

【file:/include/linux/memblock.h】
struct memblock_type {
    unsigned long cnt; /* number of regions */
    unsigned long max; /* size of the allocated array */
    phys_addr_t total_size; /* size of all regions */
    struct memblock_region *regions;
};

cnt和max分别表示当前状态(memory/reserved)的内存块可用数和可支持的最大数,total_size则表示当前状态(memory/reserved)的空间大小(也就是可用的内存块信息大小总和),而regions则是用于保存内存块信息的结构(包括基址、大小和标记等):

【file:/include/linux/memblock.h】
struct memblock_region {
    phys_addr_t base;
    phys_addr_t size;
    unsigned long flags;
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
    int nid;
#endif
};

memblock算法的主要结构体也就这么多了,总的关系如图:

image

回去看看__initdata_memblock的定义:

【file:/mm/memblock.c】
static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
struct memblock memblock __initdata_memblock = {
    .memory.regions = memblock_memory_init_regions,
    .memory.cnt = 1, /* empty dummy entry */
    .memory.max = INIT_MEMBLOCK_REGIONS,
    
    .reserved.regions = memblock_reserved_init_regions,
    .reserved.cnt = 1, /* empty dummy entry */
    .reserved.max = INIT_MEMBLOCK_REGIONS,
 
    .bottom_up = false,
    .current_limit = MEMBLOCK_ALLOC_ANYWHERE,
};

它初始化了部分成员,表示内存申请自高地址向低地址,且current_limit设为~0,即0xFFFFFFFF,同时通过全局变量定义为memblock的算法管理中的memory和reserved准备了内存空间。

接下来分析一下memblock算法初始化,其初始化函数为memblock_x86_fill(),初始化调用栈位置:

start_kernel()                          #/init/main.c

└->setup_arch()                        #/arch/x86/kernel/setup.c

└->memblock_x86_fill()                #/arch/x86/kernel/e820.c

函数实现:

【file:/arch/x86/kernel/e820.c】
void __init memblock_x86_fill(void)
{
    int i;
    u64 end;
 
    /*
     * EFI may have more than 128 entries
     * We are safe to enable resizing, beause memblock_x86_fill()
     * is rather later for x86
     */
    memblock_allow_resize();
 
    for (i = 0; i < e820.nr_map; i++) {
        struct e820entry *ei = &e820.map[i];
 
        end = ei->addr + ei->size;
        if (end != (resource_size_t)end)
            continue;
 
        if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
            continue;
 
        memblock_add(ei->addr, ei->size);
    }
 
    /* throw away partial pages */
    memblock_trim_memory(PAGE_SIZE);
 
    memblock_dump_all();
}

该函数的实现中,调用了memblock_allow_resize() 仅是用于置memblock_can_resize的值;里面的for则是用于循环遍历e820的内存布局信息,将信息做memblock_add的操作;最后循环退出后,将调用memblock_trim_memory()和memblock_dump_all()做后处理。这里首先看一下memblock_add()的函数实现:

【file:/mm/memblock.c】
int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
{
    return memblock_ad
首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇高通平台开机LOGO修改LK(bootload.. 下一篇1. Linux-3.14.12内存管理笔记【..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目