Linux内存管理专题

时间:2022-09-22 08:27:47

Linux的内存管理涉及到的内容非常庞杂,而且与内核的方方面面耦合在一起,想要理解透彻非常困难。

在开始学习之前进行了一些准备工作《如何展开Linux Memory Management学习?》,

1. 参考资料

遂决定以如下资料作为参考,进行Linux内存管理的研究:

奔跑吧 Linux内核》:以第2章为蓝本展开,这是目前能获取的紧跟当前内核发展(Linux 4.0),并且讲的比较全面的一本资料。

Understanding the Linux Virtual Memory Manager》:简单说就是虽老但经典,基于(Linux 2.4/2.6)。作者是目前仍然活跃在Linux社区MM专家。

wowotech Memory Management》:没有其他系列经典,也没有条理系列的介绍MM,但是仍然值得按考。

tolimit Linux内存源码分析》:相对零散的介绍了内存相关分析文档

Linux Kernel v4.0》:当然必不可少的,是源码了。

当逐渐深入看到MMU相关代码时,读一下ARM架构关于MMU的规格书有助于理解。

不然对于虚拟地址到物理地址的映射就会很虚无,这些资料包括《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》的《Virtual Memory System Architecture》,以及相关MMU TRM。

2. Linux Memory Management框架图

 整个内存管理从宏观上可以分为三大部分:用户空间、内核空间和相关硬件

用户空间主要是libc对相关系统调用进行封装,对用户程序提供API,常用的有malloc、mmap、munmap、remap、madvise、mempolicy等等。

相关硬件包括MMU/TLB、L1/L2 Cache以及DDR RAM,具体到ARM架构需要对照MMU/L2 Cache以及RAM规格书。

内核空间就复杂多了,首先介绍初始化及初始化后的布局。

2.1 物理内存初始化从获取内存大小、初始化页表,再进行zone初始化,然后在zone中使用伙伴系统进行物理内存初始化;

2.2 页表的映射过程讲述了ARM32和ARM64两种架构下的页表映射,如何从虚拟地址由MMU转化成物理页面地址的;

2.3 内核内存的布局图在内存被初始化之后,内核的内存布局基本上就确定了,ARM32和ARM64下布局有很大区别。在malloc一节brk中介绍了用户空间的布局。

 

2.1~2.3是内存的一个静态状态,在有了这些基础之后,2.4~2.9按照从低层到上层的逐个介绍了。

2.4 分配物理页面介绍了基于伙伴系统的页分配和释放;

2.5 slab分配器基于伙伴系统,slab分配更小内存块;以及基于slab的kmalloc;

2.6 vmalloc和kmalloc区别在于v,即在VMALLOC区域分配;

2.7 VMA即Virtual Memory Area,是进程内存管理的核心;

2.8 malloc2.9 mmap都基于VMA,malloc/free用于分配/释放一块内存;mmap/munmap用于匿名/文件映射到用户空间。

由于malloc/mmap分配内存并不是立即分配,只是在用到的时候才会触发2.10 缺页中断处理

 

在缺页但页不足的情况下,就需要进行一些操作调整内存,这些操作的基础是2.11 page引用计数,还有页面的2.12 反向映射RMAP技术。

在内存不足情况下触发kswapd2.13 回收页面,其中匿名页面有着特殊的2.14 匿名页面生命周期

在kswapd回收依然无法满足内存分配,就需要对内存进行2.16 内存规整,它依赖的技术是2.15 页面迁移

由于内存中存在一些内容完全一样的页面,使用2.17 KSM技术进行合并,同时利用COW技术,在需要时重新分配。

还介绍了2.18 Dirty COW内存漏洞,然后对内存管理数据结构和API进行了总结2.19 总结内存管理数据结构和API

最后2.20 最新更新和展望对新技术进行了介绍。

除了以上技术,还有如下内存技术:

  • swap计数把匿名页面写入SWAP分区从而释放出空闲页面
  • 内存压缩技术zram(a compressed RAM based swap device)
  • zswap技术是zram和swap的一个综合,首先将待换出页面进行压缩,存储到系统RAM动态分配的内存池中;达到一定阈值后再写入实际交换设备。
  • 在内存极端不足情况下使用21 OOM(Out-Of-Memory)来杀死不重要进程获取更多内存的技术
  • 基于cgroup的Memory资源控制
  • 解决多媒体对大量连续内存需求的CMA(Contiguous Memory Allocator)技术
  • slub分配器
  • memory hotplug内存热插拔支持动态更换内存物理设备

==============================================================================================================================

在对内存相关技术了解过后,就是如何运用的问题了?

一方面是对内存问题进行定位;另一方面是对内存行为施加影响,进行优化。

22 内存检测技术对Linux内存常见问题及其定位方法和工具(slub_debug/kmemleak/kasan)进行了讲解。

23 一个内存Oops解析以一个内存Oops为例,介绍了内存相关异常分析。

内存sysfs节点和工具介绍了linux内存管理相关sysfs节点,以及工具;借助这些可以对内存进行优化。

扩展阅读:

Linux内存管理专题

Linux内存管理框架图

3. 代码和测试环境搭建

3.1 QEMU

安装QEMU以及相关编译工具

sudo apt-get install qemu libncurses5-dev gcc-arm-linux-gnueabi build-essential

3.2 Busybox 1.24

下载Busybox 1.24代码:

git clone https://github.com/arnoldlu/busybox.git -b 1_24_stable

编译Busybox:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi- #make menuconfig #P684,进行配置 make -j4 install

 

配置initramfs:

sudo cp -r running_kernel_initramfs/* _install/
sudo chmod +x _install/etc/init.d/rcS
cd _install
mkdir mnt
mkdir dev
cd dev
sudo mknod console c 5 1
sudo mknod null c 1 3

  

3.3 Kernel 4.0

下载Linux Kernel 4.0代码:

git clone https://github.com/arnoldlu/linux.git -b running_kernel_4.0

 编译Linux Kernel:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make vexpress_defconfig #P685进行配置 make bzImage -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make dtbs

  

3.4 运行内核

#Run Kernel+Busybox in QEMU
qemu-system-arm -M vexpress-a9 -smp 4 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic

 至此,已经有一个完整的环境,提供shell命令。