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

1.1.1memblock

系统初始化的时候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,

intnid)

{

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

}

//移除操作

int__init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)

{

returnmemblock_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);

returnmemblock_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_);

returnmemblock_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中:

structmemblock {

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

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

structmemblock_type memory;//可用内存的集合

structmemblock_type reserved;//已分配内存的集合

#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP

structmemblock_type physmem;//物理内存的集合

#endif

};

memblock_region结构体描述了内存区域

structmemblock_region {

phys_addr_t base;

phys_addr_t size;

unsignedlongflags;

#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP

intnid;

#endif

};

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

结构体memblock_type

structmemblock_type {

unsignedlongcnt;/* number of regions */

unsignedlongmax;/* size of the allocated array */

phys_addr_t total_size;/* size of all regions */

structmemblock_region *regions;

char*name;

};

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

1.1.1.2memblock初始化

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

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

在文件mm/memblock.c文件中,如下所示:

staticstructmemblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;

staticstructmemblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;

#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP

staticstructmemblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;

#endif

structmemblock 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

voidmemblock_discard(void);

#else

#define __init_memblock

#define __initdata_memblock

#endif

其中INIT_MEMBLOCK_REGIONS和INIT_PHYSMEM_REGIONS定义如下:

#define INIT_MEMBLOCK_REGIONS128

#define INIT_PHYSMEM_REGIONS4

#define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)

1.1.1.3内存相关初始化

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

1.1.1.4参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值