当alloc_pages失败时,Linux内核的"内存急救"全流程解密
凌晨3点的服务器监控突然告警——某核心服务的响应延迟从20毫秒飙升至800毫秒。当你打开内核日志,看到的是一连串alloc_pages失败记录。这不是简单的内存不足告警,而是内核正在执行一场精密复杂的"内存急救"手术。本文将带你深入Linux内核的紧急内存处理机制,揭示当快速分配失败时,内核如何通过多级回收策略竭力避免系统崩溃。
1. 内存分配的快速路径为何会失败
在理想情况下,内存分配应该像超市购物一样简单:走进内存管理区(zone),从空闲列表(freelist)直接拿到所需页面。get_page_from_freelist函数就是完成这个快速路径分配的核心。但以下三种情况会导致快速路径失效:
c复制// 快速路径核心逻辑简化示意
static struct page *
get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
const struct alloc_context *ac)
{
for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx, ac->nodemask) {
if (!zone_watermark_fast(zone, order, mark, ac_classzone_idx(ac), alloc_flags))
continue; // 水位检查不通过
page = rmqueue(zone, order, migratetype, alloc_flags); // 实际分配
if (page)
return page;
}
return NULL;
}
水位线(watermark)机制是快速路径的第一道关卡。内核为每个内存管理区设置三个水位阈值:
| 水位等级 | 说明 | 典型比例(占zone总页面) |
|---|---|---|
| MIN | 最低警戒线,分配到此水位可能触发回收 | 5% |
| LOW | 低水位线,常规分配的安全边界 | 10% |
| HIGH | 高水位线,内存充足状态标志 | 25% |
当`zone_wate
