Linux 内核中的**内存管理模块(Memory Management, MM)**在运行时会维护多种状态,用于跟踪内存页、分配器、进程地址空间等的当前情况。这些状态直接影响内存分配、回收、交换等行为。以下是内存管理模块的主要状态分类及其含义:
---
### **1. 内存页(Page)的状态**
每个物理内存页(`struct page`)通过标志位和链表维护状态,主要分为以下几类:
#### **(1) 伙伴系统(Buddy System)中的页状态**
- **`free`(空闲)**
- 页位于伙伴系统的空闲链表(`free_area`)中,可被分配。
- 通过 `zone->free_area[order]` 管理不同大小的连续页块。
- **`allocated`(已分配)**
- 页被分配给内核或用户空间,可能用于:
- 内核对象(通过 `kmalloc`/`SLAB`)。
- 用户进程(通过 `page fault` 或 `mmap`)。
- 文件缓存(`Page Cache`)。
#### **(2) 页标志位(`struct page->flags`)**
通过 `enum pageflags`(`include/linux/page-flags.h`)定义页的详细状态:
- **`PG_locked`**:页被锁定(如正在I/O操作中)。
- **`PG_dirty`**:页内容已被修改(需写回磁盘)。
- **`PG_uptodate`**:页数据与磁盘一致(用于文件缓存)。
- **`PG_active`/`PG_inactive`**:页在活跃/非活跃LRU链表(影响回收策略)。
- **`PG_swapbacked`**:页可被交换到磁盘(如匿名页)。
#### **(3) 特殊用途页状态**
- **`Reserved`**:保留页(如内核启动时使用,不可分配)。
- **`CMA`(连续内存分配器)**:预留给设备驱动的大块连续内存。
- **`HugePage`**:大页(`hugetlbfs`)专用页。
---
### **2. 内存区域(Zone)的状态**
每个内存节点(`struct pglist_data`)划分为多个 `zone`(如 `ZONE_DMA`, `ZONE_NORMAL`),其状态包括:
- **`watermark`(水位线)**:
- `min`/`low`/`high`:用于触发内存回收(`kswapd` 或直接回收)。
- 当空闲页低于 `min` 时,系统可能触发 OOM(Out-of-Memory)。
- **`managed_pages`**:该 zone 中被伙伴系统管理的总页数。
- **`free_pages`**:当前空闲页数。
---
### **3. 进程地址空间(VMA)的状态**
进程的虚拟内存区域(`struct vm_area_struct`)状态:
- **`VM_READ`/`VM_WRITE`/`VM_EXEC`**:权限标志。
- **`VM_LOCKED`**:内存被锁定(不可交换)。
- **`VM_GROWSDOWN`**:栈空间可向下扩展。
- **`VM_IO`**:映射设备内存(如 `mmap` 显卡显存)。
---
### **4. 内存回收(Reclaim)状态**
- **`kswapd` 线程状态**:
- 周期性检查内存水位,后台回收页。
- 触发条件:空闲页 < `low` 水位。
- **直接回收(Direct Reclaim)**:
- 当分配内存失败时同步回收(如 `GFP_KERNEL` 分配时)。
- **LRU 链表状态**:
- **`active_list`**:近期被访问的页。
- **`inactive_list`**:候选回收页。
- 页在 `active`/`inactive` 之间迁移(通过 `mark_page_accessed()`)。
---
### **5. 交换空间(Swap)状态**
- **`Swap Cache`**:
- 已换出但未被修改的页(可快速换回)。
- **`Swap Slot` 状态**:
- `SWAP_HAS_CACHE`:换出页仍有缓存。
- `SWAP_MAP_BAD`:无效交换槽。
---
### **6. 内存压缩(Compaction)状态**
- **`COMPACT_SKIPPED`**:跳过压缩(因碎片不足)。
- **`COMPACT_SUCCESS`**:成功合并空闲页块。
- **`COMPACT_CONTINUE`**:压缩进行中。
---
### **7. OOM(Out-of-Memory)状态**
- **`oom_score`**:进程的OOM评分(越高越优先被杀死)。
- **`under_oom`**:系统正在处理OOM事件。
---
### **关键状态查询接口**
1. **查看系统内存状态**
```bash
cat /proc/meminfo # 全局内存统计(MemTotal, SwapFree等)
cat /proc/zoneinfo # 各zone的水位和碎片情况
```
2. **查看进程内存状态**
```bash
cat /proc/<pid>/maps # 进程的VMA映射
cat /proc/<pid>/status # 进程内存使用(VmRSS, VmSwap等)
```
3. **内核代码中的状态检查**
```c
PageActive(page); // 检查页是否在active链表
zone_watermark_ok(zone, order); // 检查zone水位
```
---
### **状态转换示例(页的生命周期)**
1. **分配**:
`free_area` → `alloc_pages()` → 标记为 `PG_allocated`。
2. **使用**:
文件读写 → 标记为 `PG_dirty`。
3. **回收**:
`active_list` → `inactive_list` → 写入交换区(`PG_swapbacked`)。
4. **释放**:
`free_pages()` → 返回 `free_area`。
---
### **总结**
内存管理模块的状态是多层次的,涵盖:
- **物理页**:空闲、已分配、脏页等。
- **内存区域**:水位、碎片、NUMA节点。
- **进程虚拟内存**:VMA权限、锁定状态。
- **动态行为**:回收、压缩、OOM。
这些状态通过内核数据结构和 `/proc` 文件系统暴露,是调试性能问题(如内存泄漏、碎片)的关键依据。
513

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



