linux内存初始化初期内存分配器——memblock

1.1.1 memblock

系统初始化的时候buddy系统,slab分配器等并没有被初始化好,当需要执行一些内存管理、内存分配的任务,就引入了一种内存管理器bootmem分配器。

当buddy系统和slab分配器初始化好后,在mem_init()中对bootmem分配器进行释放,内存管理与分配由buddy系统,slab分配器等进行接管。

       而memblock是用来替代bootmem的新接口。用__alloc_memory_core_early()取代了bootmem__alloc_bootmem_core()来完成内存分配.

实现都位于mm/memblock.c文件中。例如,可以通过函数memblock_reserve可以保留内存。

       此外还有如下函数:

int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,

                                       int nid)

{

        return memblock_add_range(&memblock.memory, base, size, nid, 0);

}

//移除操作

int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)

{

        return memblock_remove_range(&memblock.memory, base, size);

}

//释放操作

int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)

{

        phys_addr_t end = base + size - 1;

 

        memblock_dbg("   memblock_free: [%pa-%pa] %pF\n",

                     &base, &end, (void *)_RET_IP_);

 

        kmemleak_free_part_phys(base, size);

        return memblock_remove_range(&memblock.reserved, base, size);

}

//标记已经使用的方法

int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)

{

        phys_addr_t end = base + size - 1;

 

        memblock_dbg("memblock_reserve: [%pa-%pa] %pF\n",

                     &base, &end, (void *)_RET_IP_);

 

        return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0);

}

       为了保证系统的兼容性, 内核为bootmem和memblock提供了相同的API接口。编译Kernel的时候可以选择nobootmem或者bootmem 来在buddy system起来之前管理memory(参数CONFIG_NO_BOOTMEM)。默认是选择memblock的。

1.1.1.1  数据结构

memblock把物理内存划分为若干内存区,按使用类型分别放在memory和reserved两个集合(数组)中,memory即动态内存的集合,reserved集合包括静态内存和预留内存;

定义在文件include/linux/memblock.h中:

struct memblock {

        bool bottom_up;  /* is bottom up direction? 是否允许从下往上分配内存*/

        phys_addr_t current_limit;//内存块限制,限制memblock_alloc内存申请

        struct memblock_type memory;//可用内存的集合

        struct memblock_type reserved;//已分配内存的集合

#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP

        struct memblock_type physmem;//物理内存的集合

#endif

};

memblock_region结构体描述了内存区域

struct memblock_region {

        phys_addr_t base;

        phys_addr_t size;

        unsigned long flags;     

#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP

        int nid;

#endif

};

其中base是内存区域其实地址,size是内存区域大小,flags是标记,nid是node号。

结构体memblock_type

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;

        char *name;

};

其中cnt是当前集合记录的内存区域个数,max是当前集合记录的内存区域最大个数,total_size是集合记录区域信息大小,regions内存区域结构指针。

1.1.1.2  memblock初始化

以上是memblock的三个结构体和相关函数说明,下面来看下memblock的初始化。

       内核编译时候,会分配好memblock结构所需要的内存空间。

       在文件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;

#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP

static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;

#endif

struct memblock memblock __initdata_memblock = {

        .memory.regions         = memblock_memory_init_regions,

        .memory.cnt             = 1,    /* empty dummy entry */

        .memory.max             = INIT_MEMBLOCK_REGIONS,

        .memory.name            = "memory",

 

        .reserved.regions       = memblock_reserved_init_regions,

        .reserved.cnt           = 1,    /* empty dummy entry */

        .reserved.max           = INIT_MEMBLOCK_REGIONS,

        .reserved.name          = "reserved",

 

#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP

        .physmem.regions        = memblock_physmem_init_regions,

        .physmem.cnt            = 1,    /* empty dummy entry */

        .physmem.max            = INIT_PHYSMEM_REGIONS,

        .physmem.name           = "physmem",

#endif

 

        .bottom_up              = false,

        .current_limit          = MEMBLOCK_ALLOC_ANYWHERE,

};

其中__initdata_memblock宏指定存储位置

#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK

#define __init_memblock __meminit

#define __initdata_memblock __meminitdata

void memblock_discard(void);

#else

#define __init_memblock

#define __initdata_memblock

#endif

其中INIT_MEMBLOCK_REGIONSINIT_PHYSMEM_REGIONS定义如下:

#define INIT_MEMBLOCK_REGIONS   128

#define INIT_PHYSMEM_REGIONS    4

#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)

1.1.1.3  内存相关初始化

在内核初始化初期,通过int 0x15来被探测和整理物理内存, 存放到e820中。而memblock初始化就发生在这个以后.

 

1.1.1.4  参考

mm: Use memblock interface instead of bootmem

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值