由于其天然的稀缺性和复杂性,内存管理(Memory Management,简称MM)成为Linux内核中一个极为重要且复杂的子系统
本文将从多个角度对Linux内核内存管理进行深入解析,并探讨其重要性
一、内存管理的基本需求 在嵌入式系统中,从需求的角度来看,内存可以简单地分为两大类: 1.CPU的内存访问需求:CPU需要从内存中读取指令和数据,或者向内存中写入数据
相应的数据流为:CPU<------>MMU(可选)<------->Memory
2.外部设备的内存访问需求:设备需要从内存中读取数据或向内存中写入数据
由于大多数设备不像CPU那样具备直接访问内存的能力,它们访问内存主要有三种途径: - 由CPU中转,数据流为:Device<------>CPU<------>Memory
- 由第三方智能模块(如DMA控制器)中转,数据流为:Device<------>DMA Controller<------>Memory
- 直接访问内存,数据流为:Device<------>IOMMU(可选)<------>Memory
二、Linux内核内存管理的视角 Linux内核内存管理模块需要从CPU和设备两个视角来理解并满足上述需求
1. CPU视角 在具有MMU功能的嵌入式Linux平台上,CPU对内核内存管理模块的需求可以概括为以下几点: - 看到内存:在MMU使能之前,内核可以很容易地看到物理内存
但在MMU使能后、内存管理机制准备就绪之前,内核看到的是虚拟地址
此时需要一种简单有效的机制来建立虚拟内存到物理内存的映射
- 管理内存:看到内存后,下一步是将它们管理起来
根据内存的不同形态(如是否连续、是否具有NUMA内存、是否具有可拔插的内存等),可能采用不同的管理模型和方法
- 提供服务:管理内存后,内核需要向其他模块(如内核线程、用户空间进程等)提供服务,包括: - 提供远大于物理内存的虚拟地址空间
- 确保每个进程都有独立的虚拟地址空间,以提供内存保护
- 提供内存映射机制,将物理内存、I/O空间、内核映像、文件等对象映射到相应进程的地址空间中
- 提供公平、高效的物理内存分配算法
- 提供进程间内存共享的方法(以虚拟内存的形式)
- 高级内存管理需求:在基础服务提供后,更高级的需求也随之产生,如内存的热拔插、处理高内存、超大页支持、交换页机制、页面迁移、内存泄漏检查、内存碎片整理、内存不足时的处理等
2. Device视角 当软件操作一些特殊的硬件设备时,麻烦就会出现
由于这些设备不能像CPU那样直接访问内存,因此内存管理模块需要为它们提供特殊的接口,以便按照设备所期望的形式组织内存
这就是在编写设备驱动时经常遇到的DMA映射功能
此外,在某些应用场景下,内存数据可能会在多个设备间流动
为了提高效率,不能为每个设备都提供一份拷贝,因此内存管理模块需要提供设备间内存共享(以及相互转换)的功能
三、Linux内核内存管理的软件结构 基于上述需求,Linux内核从虚拟内存(VM)、DMA映射以及DMA缓冲区共享三个角度对内存进行管理
- 虚拟内存(VM):是内存管理的主要模块,代码主要分布在mm/以及arch/xxx/mm/两个目录下
其中,arch/xxx/mm/提供平台相关部分的实现,mm/提供平台无关部分的实现
- DMA映射:是内存管理的辅助模块,主要提供dma_alloc_xxx(申请可供设备直接访问的内存)和dma_map_xxx(在CPU视角的虚拟内存和dma_addr之间转换)两类接口
- DMA缓冲区共享:允许多个设备共享同一块内存区域,以提高效率
四、Kernel Shared Memory(KSM)技术 在Linux内核2.6.32版本中,引入了一个有趣的变化——Kernel Shared Memory(KSM)
KSM允许系统管理程序通过合并内存页面来增加并发虚拟机的数量
虚拟化技术使得多个操作系统和应用程序可以共享一个服务器,从而提高了基础设施的动态性、节能性和经济性
当多个虚拟机(VM)运行相同的操作系统和应用程序代码时,它们的内存页面可能是相同的
KSM通过合并这些相同的页面来释放内存,供其他应用程序使用
KSM作为内核中的一个守护进程(称为ksmd)存在,它定期执行页面扫描,识别并合并副本页面
这个过程对用户是透明的
当一个页面的内容发生变化时,KSM会使用写时复制(Copy-On-Write,CoW)机制为该页面创建副本
KSM不仅适用于虚拟环境,还可以用于非虚拟环境和嵌入式Linux系统
它通过使用红黑树来管理页面,其中一个树用于存储不稳定的页面(即那些还不能确定为稳定的页面),另一个树用于存储已确定稳定的页面
五、内存管理的早期分配器 在系统初始化早期,由于正常的内存管理还未完成设置,因此需要引入一种专用的内存分配器
Boot Memory Allocator(bootmem)就是为此目的而设计的
几年后,PowerPC开发人员添加了Logical Memory Blocks(memblock)分配器,后来被其他架构采用
memblock将系统内存视为连续区域的集合,包括描述内核可用的物理内存区域的memory类型和描述已分配的内存区域的reserved类型
每种内存类型都由struct memblock_type描述,其中包含内存区域数组以及元数据
在早期进行架构相关的
Linux环境下MQTT应用实战指南
深入解析Linux内核内存管理
hyper183单元:创新科技引领未来趋势
Linux下图片合成动画实战指南
掌握Linux独立空间:打造个性化高效工作环境
超神降临:解锁Hyper Carry的终极奥义
Linux系统内存监控实战技巧
Linux环境下MQTT应用实战指南
Linux下图片合成动画实战指南
掌握Linux独立空间:打造个性化高效工作环境
Linux系统内存监控实战技巧
Linux开源许可:解锁创新潜能的钥匙
掌握Linux系统:详解dpkg -l命令列出已安装软件包
Linux4.9.97内核更新亮点解析
乐高式搭建:探索Linux系统的无限可能
XAMPP Linux命令:搭建本地开发环境的秘籍
网易游戏在Linux平台上的精彩表现与探索
Linux系统下快速连接本地MySQL指南
掌握Linux:详解reboot命令用法