内核内存布局和堆管理
通过
输出地址大小,具体其他选项参数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),具体内核源码如下:
brk系统调用内核源码如下:
Linux系统当中有两个方法可以创建堆
brk()是系统调用,实际是设置进程数据段的结束地址,将数据段的结束地址向高地址移动。
mmap()向操作系统申请一段虚拟地址空间(使用映射到某个文件)。当不用此空间来映射到某个文件时,这块空间称为匿名空间,可以用来作为堆空间。
per-CPU计数器
引入它用来加速SMP系统上计数器的操作。
案例分析如下:
作者:徐锦桐
链接:https://www.xujintong.com/2023/10/30/36/
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)