Linux 内核中的**内存管理模块(Memory Management, MM)**负责物理内存、虚拟内存的分配与回收,地址空间管理,页表操作等核心功能。其边界主要通过以下方式划分,确保与其他模块的隔离和协作:
---
### **1. 模块边界(功能划分)**
#### **(1)物理内存管理(Page Allocator)**
- **功能**:管理物理页帧(`struct page`),处理分配/释放(如 `alloc_pages()`, `free_pages()`)。
- **边界**:
- **依赖**:硬件架构相关代码(如 `arch/x86/mm` 处理页表映射)。
- **提供接口**:
- `include/linux/gfp.h`:`GFP_KERNEL`/`GFP_ATOMIC` 等分配标志。
- `mm/page_alloc.c`:`alloc_pages()`, `__get_free_pages()`。
#### **(2)虚拟内存管理(VM Subsystem)**
- **功能**:管理进程地址空间(`struct mm_struct`)、缺页异常(Page Fault)、内存映射(`mmap()`)。
- **边界**:
- **依赖**:文件系统(如 `mmap()` 文件映射依赖 VFS)。
- **提供接口**:
- `mm/mmap.c`:`do_mmap()`, `do_munmap()`。
- `mm/memory.c`:缺页处理(`handle_mm_fault()`)。
#### **(3)SLAB/SLUB 分配器**
- **功能**:高效管理内核对象(如 `task_struct`, `inode` 缓存)。
- **边界**:
- **依赖**:物理页分配器(底层调用 `alloc_pages()`)。
- **提供接口**:
- `include/linux/slab.h`:`kmalloc()`, `kmem_cache_create()`。
#### **(4)交换空间(Swap)**
- **功能**:将匿名页换出到磁盘。
- **边界**:
- **依赖**:块设备驱动(读写交换分区)。
- **提供接口**:
- `mm/swap_state.c`:`add_to_swap()`, `swapin_readahead()`。
#### **(5)内存控制组(cgroups)**
- **功能**:限制进程组内存使用(如 `cgroup v2` 的 `memory.limit_in_bytes`)。
- **边界**:
- **依赖**:核心调度器(关联进程与 cgroup)。
- **提供接口**:
- `mm/memcontrol.c`:`mem_cgroup_charge()`。
---
### **2. 与其他模块的交互边界**
#### **(1)与进程管理模块**
- **交互**:进程创建时分配地址空间(`copy_mm()`),退出时释放内存。
- **接口**:
- `kernel/fork.c`:`dup_mm()`(复制进程内存)。
- `exit_mm()`(释放内存)。
#### **(2)与文件系统模块**
- **交互**:文件映射(`mmap()`)和页面缓存(`Page Cache`)。
- **接口**:
- `mm/filemap.c`:`filemap_fault()`(处理文件缺页)。
- `fs/aio.c`:异步 I/O 内存操作。
#### **(3)与设备驱动模块**
- **交互**:DMA 内存分配(`dma_alloc_coherent()`)、设备内存映射(`ioremap()`)。
- **接口**:
- `include/linux/dma-mapping.h`:DMA API。
- `arch/x86/mm/ioremap.c`:`ioremap()`(映射设备内存到内核空间)。
#### **(4)与网络模块**
- **交互**:SKB 缓冲区分配(`net/core/skbuff.c` 使用 `kmalloc()`)。
- **接口**:
- `struct sk_buff` 的 `alloc_skb()` 依赖 SLAB。
#### **(5)与虚拟化模块**
- **交互**:客户机物理内存管理(如 KVM 的 `EPT` 页表)。
- **接口**:
- `virt/kvm/kvm_main.c`:`kvm_vm_ioctl()`(内存区域注册)。
---
### **3. 关键数据结构与API**
#### **(1)核心数据结构**
- `struct page`:描述物理页帧。
- `struct mm_struct`:进程地址空间。
- `struct vm_area_struct`(VMA):虚拟内存区域。
#### **(2)关键API**
| **功能** | **接口/函数** | **头文件/源码** |
|------------------------|---------------------------------------|--------------------------|
| 物理页分配 | `alloc_pages()`, `__free_pages()` | `include/linux/gfp.h` |
| 虚拟内存映射 | `mmap()`, `munmap()`(系统调用) | `mm/mmap.c` |
| 内存回收 | `kswapd`(内核线程) | `mm/vmscan.c` |
| 缺页异常处理 | `handle_mm_fault()` | `mm/memory.c` |
| DMA内存分配 | `dma_alloc_coherent()` | `include/linux/dma-map.h` |
---
### **4. 边界隔离机制**
1. **符号导出控制**
- 仅通过 `EXPORT_SYMBOL()` 公开必要函数(如 `kmalloc` 导出,但 `__get_free_pages` 内部使用)。
2. **权限检查**
- 用户空间内存访问需通过 `copy_to_user()`/`copy_from_user()`。
3. **内存隔离**
- 进程间通过页表隔离(`mm_struct` 独立)。
4. **cgroups 限制**
- 防止进程组耗尽系统内存。
---
### **5. 示例:模块交互流程**
#### **场景:进程通过 `mmap()` 映射文件**
1. **用户层**:调用 `mmap()` 系统调用。
2. **VFS 层**:处理文件描述符,调用 `file->f_op->mmap()`。
3. **内存模块**:
- 创建 VMA(`mmap_region()`)。
- 触发缺页时,调用文件系统的 `filemap_fault()` 加载文件内容到页面缓存。
4. **文件系统**:从磁盘读取数据到内存页(`readpage()`)。
---
### **总结**
内存管理模块的边界由以下要素定义:
1. **功能分层**:物理页管理 → 虚拟内存 → 缓存/交换。
2. **接口抽象**:通过头文件暴露 API(如 `gfp.h`, `slab.h`)。
3. **依赖关系**:与进程、文件系统、驱动等模块通过严格接口交互。
4. **隔离机制**:符号导出控制、权限检查、cgroups。
开发者应避免直接操作内部数据结构(如 `struct page`),始终使用公开API,以确保兼容性和稳定性。
3589

被折叠的 条评论
为什么被折叠?



