内核内存布局和堆管理

通过 cat /proc/cpuinfo输出地址大小,具体其他选项参数

vendor_id       : AuthenticAMD   // CPU制造商
cpu family      : 23    // CPU产品代号
model           : 96      // CPU属于其系列当中的哪一个代号
model name      : AMD Ryzen 5 4600H with Radeon Graphics       // CPU属于的名称、编号、主频
stepping        : 1 // CPU属于制作更新版本
cpu MHz         : 2994.371   // CPU实际使用主频
cache size      : 512 KB  // CPU二级缓存
physical id     : 0   // 单个CPU的标号
siblings        : 12    // 单个CPU逻辑物理核数
core id         : 0   // 当前物理核 在其所处的CPU中编号
cpu cores       : 6   // 逻辑核所在CPU的物理核数
apicid          : 0    // 0用来区分不同逻辑
bogomips        : 5988.74  // 系统内核启动时测算的CPU速度
TLB size        : 3072 4K pages
clflush size    : 64  // 每次刷新缓存的大小单位
cache_alignment : 64   // 缓存地址空间对齐单位
address sizes   : 48 bits physical, 48 bits virtual  // 可以访问的地址空间位数

通过`` cat /proc/meminfo``输出系统架构内存分布情况,具体如下。

MemTotal:        8068204 kB       // 所有可用内存空间的大小
MemFree:         2631432 kB // 系统还没有使用的内存
MemAvailable:    6263804 kB   // 真正系统可用的内存
Buffers:          138132 kB // 专门用来给快设备做缓存的内存
Cached:          3486024 kB   // 分配给文件缓冲区的内存
SwapCached:            0 kB // 被调整缓冲缓存使用的交换空间大小
Active:          1939496 kB // 使用高速缓冲存储器页面文件大小
Inactive:        2763020 kB  // 没有经常使用的高速缓存存储器页面大小
Active(anon):       2456 kB  // 活跃的匿名内存
Inactive(anon):  1080476 kB  // 不活跃的域名内存
Active(file):    1937040 kB  // 活跃的文件使用内存
Inactive(file):  1682544 kB  // 不活跃的文件使用内存
Unevictable:           0 kB // 不能被释放的内存页
Mlocked:               0 kB   // 系统调用mlock允许程序在物理内存上锁住部分或全部地址空间
SwapTotal:       2097152 kB // 交换空间总内存大小
SwapFree:        2097152 kB   // 交换空间空闲的内存大小
Dirty:                 0 kB     // 等待被写回到磁盘
Writeback:             0 kB  // 正在被写加的大小
AnonPages:       1040516 kB  // 未映射的内存/映射到用户空间的非文件页表大小
Mapped:           440388 kB // 映射文件内存
Shmem:              4572 kB  // 已经被分配的共享内存
KReclaimable:     313312 kB  // 可回收的slab内存
Slab:             413356 kB // 内存数据结构缓存大小
CommitLimit:     6131252 kB   // 系统实际可以分配内存
Committed_AS:    4633056 kB  // 系统当前已经分配的内存
VmallocTotal:   34359738367 kB   // 预留虚拟内存的总量
VmallocUsed:       36668 kB  // 已经被使用的虚拟内存
VmallocChunk:          0 kB  可分配的最大逻辑地址连续的虚拟内存

linux内存动态内存分配通过系统接口实现

alloc _pages/__get_free_page: 以页为单位分配
vmalloc: 以字节为单位分配虚拟地址连续的内存块

kmalloc: 以字节为单位分配物理地址连续的内存块,它是以slab为中心

我们也可以通过vmalloc分配的内存将它统计输出,具体如下:

Linux内核内存布局(ARM64架构处理器内存分布图)具体如下:

ARM64机构物理地址48位寻址,最大寻找256TB的物理地址空间。

内核空间(User space):0x0000_0000_0000_0000至Ox0000_FFFF_FFFF_FFFF。

内核空间(Kernel space):0xFFFF_0000_0000_0000至0xFFFF_FFFF_FFFF_FFFF。

KASAN(影子区):它是一个动态检测内存错误的工具,原理利用额外的内存标记可用内存的状态(将1/8内存作为影子区)。

modules:内核模块使用的虚拟地址空间;

vmalloc:vmalloc函数使用的虚拟地址空间

.text:代码段

.init:模块初始化的数据

.data:数据段

.bss:静态内存分配的段

fixed:固定映射区

PCI I/O:针对PCI设备的I/O地址空间

vmemmap:内存的物理地址如果不连续的话,就会存在内存空洞(稀疏内存)vmemmap就用来存放系数内存的page结构体的数据的虚拟地址空间。

memory:线性映射区域

我们可以通过内存布局打印输出(Linux内核初始化完成后,整体布局稳定。通过Vexpress平台输出即可):

堆管理

进程中主要用于动态分配变量和数据的内存区域。malloc,new的内存。malloc和内核之间的经典接口是brk系统调用,负责拓展/收缩堆。

堆拓展时自下至上增长。其中mm_struct结构,包含堆在虚拟地址空间中的起始和当前计数地址(start_brk和brk),具体内核源码如下:

mm_struct

Snipaste_2023-10-30_15-23-15

brk系统调用内核源码如下:

Snipaste_2023-10-30_15-27-42

Linux系统当中有两个方法可以创建堆

brk()是系统调用,实际是设置进程数据段的结束地址,将数据段的结束地址向高地址移动。

mmap()向操作系统申请一段虚拟地址空间(使用映射到某个文件)。当不用此空间来映射到某个文件时,这块空间称为匿名空间,可以用来作为堆空间。

per-CPU计数器

引入它用来加速SMP系统上计数器的操作。

Snipaste_2023-10-30_15-37-26

案例分析如下:

per-CPU

THE END