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

目录
相关文章
|
20天前
|
编译器 C语言 C++
【C语言】memset()函数(内存块初始化函数)
【C语言】memset()函数(内存块初始化函数)
24 0
|
23天前
|
存储 算法 Linux
【Linux 应用开发 共享内存】深入理解和实践 ftruncate:共享内存的有效管理
【Linux 应用开发 共享内存】深入理解和实践 ftruncate:共享内存的有效管理
54 5
|
11天前
|
存储 缓存 监控
Linux内存和硬盘空间管理技巧
了解Linux内存和硬盘管理技巧,提升系统性能和稳定性。使用`free`, `top`, `vmstat`监控内存,通过`sync`, `echo 1 > /proc/sys/vm/drop_caches`清理缓存。利用Swap分区释放内存。借助`df`, `du`检查硬盘空间,清理无用文件,使用`clean-old`, `gzip`, `tar`压缩归档。查找大文件用`find`和`du`,确保
32 0
|
12天前
|
Prometheus 监控 Cloud Native
【Linux】查看系统内存命令(详细讲解)
【Linux】查看系统内存命令(详细讲解)
|
16天前
|
存储 缓存 监控
深入解析linux内存指标:快速定位系统内存问题的有效技巧与实用方法(free、top、ps、vmstat、cachestat、cachetop、sar、swap、动态内存、cgroops、oom)
深入解析linux内存指标:快速定位系统内存问题的有效技巧与实用方法(free、top、ps、vmstat、cachestat、cachetop、sar、swap、动态内存、cgroops、oom)
|
24天前
|
存储 缓存 监控
Linux 系统 内存通用指标以及查询方式
Linux 系统 内存通用指标以及查询方式
18 0
|
24天前
|
存储 Linux 程序员
【Linux C/C++ 堆内存分布】深入理解Linux进程的堆空间管理
【Linux C/C++ 堆内存分布】深入理解Linux进程的堆空间管理
70 0
|
24天前
|
存储 算法 Linux
深入理解Linux内存管理brk 和 sbrk 与以及使用C++ list实现内存分配器
深入理解Linux内存管理brk 和 sbrk 与以及使用C++ list实现内存分配器
32 0
|
30天前
|
存储 JSON 监控
Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
【2月更文挑战第30天】Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
14 1
|
1月前
|
存储 C语言
C语言--------数据在内存中的存储
C语言--------数据在内存中的存储
26 0