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

目录
相关文章
|
7天前
|
Linux
Linux rsyslog占用内存CPU过高解决办法
该文档描述了`rsyslog`占用内存过高的问题及其解决方案。
30 4
|
12天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
1天前
|
存储 缓存 监控
|
3天前
|
存储 Web App开发 运维
|
3天前
|
Java
SpringBoot 项目启动初始化一个Map对象到内存
SpringBoot 项目启动初始化一个Map对象到内存
|
3天前
|
算法 安全 Linux
深度解析:Linux内核内存管理机制
【4月更文挑战第30天】 在操作系统领域,内存管理是核心功能之一,尤其对于多任务操作系统来说更是如此。本文将深入探讨Linux操作系统的内核内存管理机制,包括物理内存的分配与回收、虚拟内存的映射以及页面替换算法等关键技术。通过对这些技术的详细剖析,我们不仅能够理解操作系统如何高效地利用有限的硬件资源,还能领会到系统设计中的性能与复杂度之间的权衡。
|
5天前
|
监控 Linux
【专栏】如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
【4月更文挑战第28天】在 Linux 中,掌握检查内存使用情况至关重要,因为内存问题可能导致系统性能下降甚至崩溃。本文介绍了 5 个常用的检查内存命令:1) `free` 提供内存和交换区的详细信息;2) `top` 显示进程信息及内存使用;3) `vmstat` 输出系统综合信息,包括内存动态变化;4) `pidstat` 监控特定进程的内存使用;5) `/proc/meminfo` 文件提供系统内存详细数据。了解和使用这些命令能帮助用户及时发现并解决内存相关问题,确保系统稳定运行。
|
10天前
|
消息中间件 Linux
【linux进程间通信(二)】共享内存详解以及进程互斥概念
【linux进程间通信(二)】共享内存详解以及进程互斥概念
|
23天前
|
存储 缓存 算法
Linux内存管理笔记----TLB
Linux内存管理笔记----TLB
25 0
|
25天前
|
存储 缓存 监控
Linux内存和硬盘空间管理技巧
了解Linux内存和硬盘管理技巧,提升系统性能和稳定性。使用`free`, `top`, `vmstat`监控内存,通过`sync`, `echo 1 > /proc/sys/vm/drop_caches`清理缓存。利用Swap分区释放内存。借助`df`, `du`检查硬盘空间,清理无用文件,使用`clean-old`, `gzip`, `tar`压缩归档。查找大文件用`find`和`du`,确保
36 0