用途
该技能用于引导智能体处理 Linux 内核内存分配相关任务,覆盖物理页分配器(buddy)、SLUB kmalloc 缓存、vmalloc 虚拟映射、内存区(DMA/Normal)以及驱动程序中的安全分配模式,是对 kernel/kernel-internals 技能的扩展。
适用时机
- 在 kmalloc、vmalloc、get_free_pages 之间做选择
- 调试内核 OOM 或 slab 损坏
- 处理 DMA 缓冲区分配需求
- 理解 /proc/meminfo 与 slab 统计
工作流程
1. 分配器决策树
需要物理连续内存用于 DMA?
├── 是 → dma_alloc_coherent() 或 CMA pool
└── 否
├── 大小 ≤ ~128K(依赖架构)→ kmalloc / kzalloc
├── 较大或允许非连续 → vmalloc / vzalloc
└── 整页 → alloc_pages() / __get_free_pages()
2. kmalloc 与 SLUB
SLUB 是默认的通用 kmalloc 后端;旧版 SLAB 分配器已在 Linux 6.12 中移除。
void *buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
/* ... */
kfree(buf);
GFP 标志:
| GFP 标志 | 上下文 |
|---|---|
| GFP_KERNEL | 进程上下文,可能睡眠 |
| GFP_ATOMIC | IRQ / 持有自旋锁——使用更小的池 |
| GFP_DMA | DMA 区(旧式 32 位设备) |
可通过 /proc/slabinfo 和 cat /sys/kernel/slab/*/object_size 检查。
3. vmalloc
void *v = vmalloc(size); /* 虚拟连续,物理分散 */
vfree(v);
适用于不需要物理连续页的大缓冲区。若用于 DMA,须先使用 dma_map_*。
4. 伙伴页分配器
struct page *page = alloc_pages(GFP_KERNEL, order);
void *addr = page_address(page);
__free_pages(page, order);
order n 分配 2^n 个页。内存区选择:ZONE_DMA、ZONE_NORMAL、ZONE_MOVABLE(参见 include/linux/mmzone.h)。
5. NUMA 基础
在 NUMA 系统上,kmalloc 优先本地节点;HPC 路径可使用 alloc_pages_node() 或 mbind 策略,另见 skills/allocators/numa-programming。
6. 调试
cat /proc/meminfo
cat /proc/slabinfo
dmesg | grep -i oom
内核配置:CONFIG_SLUB_DEBUG、CONFIG_KASAN(用于 use-after-free 检测)。
7. 智能体用法
/kernel-memory-management 在进程上下文中为 2 MiB 驱动环形缓冲区选择分配器
常见问题
| 症状 | 原因 | 修复 |
|---|---|---|
| kmalloc 大块失败 | 超出 kmalloc 上限 | 改用 vmalloc 或页分配 |
| DMA 缓冲区错误 | 用 vmalloc 做硬件 DMA | 使用 dma_alloc_coherent |
| OOM killer | 缓存无界增长 | 限制池;使用 shrinker |
| Slab 损坏 | use-after-free | KASAN;检查 kfree 配对 |
| IRQ 中使用 GFP_KERNEL | 原子上下文调用可睡眠分配器 | 改用 GFP_ATOMIC |
相关技能
- skills/kernel/kernel-internals——page cache、OOM killer
- skills/kernel/device-drivers——dma_alloc_coherent
- skills/allocators/custom-allocators——用户态分配器设计
- skills/allocators/numa-programming——NUMA 感知分配
- skills/runtimes/sanitizers——KASAN 重叠