1. 内存管理概述:物理内存与虚拟内存概念、MMU的作用、内核空间与用户空间划分

内存管理是操作系统内核最核心的子系统之一,它直接决定了系统的稳定性、性能与安全性。在嵌入式Linux内核裁剪场景中,理解内存管理的基本概念是进行后续精简与优化的前提。本节将围绕物理内存与虚拟内存的本质、内存管理单元(MMU)的硬件机制以及内核/用户空间的划分展开。

1.1 物理内存与虚拟内存

物理内存(Physical Memory)是硬件实际提供的RAM存储介质,通常以页框(Page Frame)为单位进行管理,大小为4KB(ARM64或x86_64默认)。物理内存的地址空间受限于硬件容量,例如512MB或1GB。

虚拟内存(Virtual Memory)是操作系统为每个进程提供的独立、连续的地址空间抽象。进程看到的地址是虚拟地址(VA),通过MMU硬件转换为物理地址(PA)。虚拟内存使得每个进程可以拥有独立的地址空间,互不干扰,并且允许“超额使用”物理内存(通过交换或页面回收)。

特性 物理内存 虚拟内存
地址空间 受限于硬件容量(如512MB) 受限于CPU位数(32位:4GB,64位:理论16EB)
分配单位 页框(Page Frame) 页(Page)
连续性 物理上可能不连续 对进程呈现连续线性空间
隔离性 所有进程共享 每个进程独立,互不干扰
管理主体 内核页分配器(Buddy System) 内核VMA + MMU硬件
裁剪要点:在嵌入式系统中,若物理内存极小(如64MB以下),可考虑禁用交换(Swap)并关闭高端内存支持,以简化虚拟内存管理路径,减少内核代码体积。

1.2 MMU的作用

内存管理单元(Memory Management Unit, MMU)是CPU内部负责虚拟地址到物理地址转换的硬件模块。MMU的核心功能包括:

  • 地址转换:将虚拟地址(VA)通过页表(Page Table)查找转换为物理地址(PA)。
  • 权限检查:检查当前访问是否具有读、写、执行权限,防止非法访问。
  • 缓存控制:控制页面的缓存属性(Cacheable/Non-cacheable、Write-back/Write-through)。
  • TLB加速:通过转换后备缓冲区(TLB)缓存最近使用的页表项,加速地址转换。
MMU转换流程(简化): CPU发出VA → MMU截获 → 查询TLB(命中则直接得到PA)→ TLB未命中则遍历页表(多级页表)→ 获取PA → 检查权限 → 访问物理内存。
MMU地址转换流程 CPU核心 发出VA MMU 地址转换 + 权限检查 TLB 快速缓存 页表 多级页表遍历 物理内存 PA访问 说明 MMU负责将CPU发出的虚拟地址转换为物理地址,TLB加速命中,未命中则遍历多级页表。

1.3 内核空间与用户空间划分

在Linux中,虚拟地址空间被划分为两个主要区域:内核空间(Kernel Space)和用户空间(User Space)。这种划分是系统安全与稳定性的基石。

  • 用户空间:运行用户进程(应用程序),权限受限,不能直接访问硬件或内核数据结构。访问内核必须通过系统调用(syscall)接口。
  • 内核空间:运行操作系统内核代码(调度器、驱动、文件系统等),拥有最高权限(Ring 0 / EL1),可以直接访问所有物理内存和硬件。

在32位系统中,典型的划分比例为:用户空间3GB(0x00000000 ~ 0xBFFFFFFF),内核空间1GB(0xC0000000 ~ 0xFFFFFFFF)。在64位系统中,划分比例更为灵活,通常用户空间与内核空间各占一半(如48位地址空间下,用户空间0x0000000000000000 ~ 0x00007FFFFFFFFFFF,内核空间0xFFFF800000000000 ~ 0xFFFFFFFFFFFFFFFF)。

属性 用户空间 内核空间
特权级别 低(Ring 3 / EL0) 高(Ring 0 / EL1)
访问硬件 不允许 允许
内存访问范围 仅限用户空间 全部物理内存 + 用户空间(通过copy_from_user等)
崩溃影响 仅影响当前进程 可能导致整个系统崩溃(Kernel Panic)
典型代码 应用程序、C库 内核、驱动、文件系统
内核空间与用户空间划分 用户空间 (User Space) 进程A | 进程B | 进程C | ... 特权级: Ring 3 / EL0 | 访问受限 系统调用 (syscall) 边界 内核空间 (Kernel Space) 进程管理 | 内存管理 | 文件系统 | 驱动 特权级: Ring 0 / EL1 | 完全硬件访问 用户空间通过系统调用陷入内核,内核完成服务后返回用户空间。这种隔离机制保障了系统安全。
裁剪风险提示:在裁剪内核时,切勿随意移除内核空间与用户空间之间的隔离机制(如禁用MMU或关闭SMEP/SMAP)。这会导致用户进程可以直接访问内核内存,引发严重的安全漏洞。对于没有MMU的微控制器(如Cortex-M系列),Linux提供了CONFIG_MMU=n的NOMMU模式,但功能受限且不适用于标准Linux应用。

1.4 地址空间布局示例(32位ARM)

以典型的32位ARM Linux为例,虚拟地址空间布局如下:

0xFFFFFFFF  ┌─────────────────────────────┐
            │  内核空间 (1GB)              │
            │  - 内核代码/数据             │
            │  - vmalloc区域               │
            │  - 固定映射区                │
            │  - 高端内存映射区            │
0xC0000000  ├─────────────────────────────┤
            │  用户空间 (3GB)              │
            │  - 栈 (向下增长)             │
            │  - 堆 (向上增长)             │
            │  - 数据段 (.data/.bss)       │
            │  - 代码段 (.text)            │
0x00000000  └─────────────────────────────┘

在嵌入式裁剪中,若物理内存小于1GB,可考虑关闭HIGHMEM支持(CONFIG_HIGHMEM=n),简化内核地址映射,减少TLB压力并降低内核代码量。

关键命令速查:查看当前系统的内存划分信息:
cat /proc/meminfo — 查看物理内存总量、空闲、缓存等
cat /proc/self/maps — 查看当前进程的虚拟地址空间映射
free -h — 查看系统内存使用概况