☰
page_alloc nr_free_zone_pages
2026/10/14 6:29:19 网站建设 项目流程

nr_free_zone_pages()是用于统计指定高位 zone 范围内空闲页总数的辅助函数,主要用于/proc/meminfo中FreeSwap之外的MemFree/MemAvailable等统计,以及内存回收、水位判断等场景。

核心作用与背景

它回答的问题是:从当前 zone 开始,向上(更高 zone)一共有多少空闲页?参数offset指定了起始 zone 的索引,函数会统计从该 zone 到ZONE_MOVABLE(最高 zone)之间的所有空闲页。

典型实现

static unsigned long nr_free_zone_pages(int offset) { struct zoneref *z; struct zone *zone; /* 只统计比 offset 更高(含)的 zone 的空闲页 */ unsigned long sum = 0; for_each_zone_zonelist_nodemask(zone, z, &contig_zonelist, offset, NULL) { if (!populated_zone(zone)) continue; sum += zone_page_state(zone, NR_FREE_PAGES); } return sum; }

(具体实现随版本,核心是遍历 zone 并累加NR_FREE_PAGES。)

关键点解析

1.offset参数的含义

  • offset是 zone 索引(enum zone_type的值)。

  • 函数统计的是从offset开始、到最高 zone 为止的所有 zone。

  • 例如offset = ZONE_NORMAL,则统计ZONE_NORMAL、ZONE_HIGHMEM、ZONE_MOVABLE等。

  • 这与GFP标志决定的“允许的最高 zone”相反——highest_zoneidx是上限,而offset是下限。

2.contig_zonelist

  • 这是node_zonelist(0, GFP_KERNEL)或类似的东西,代表从节点 0 开始的 zonelist。

  • 使用 zonelist 遍历宏可以正确处理 NUMA 节点关系。

3.zone_page_state(zone, NR_FREE_PAGES)

  • 读取 zone 的NR_FREE_PAGES计数。

  • 这个计数是 per-CPU 差分的汇总值,包含 PCP 缓存和伙伴系统中的空闲页。

4.populated_zone()检查

  • 跳过没有内存的 zone(如某些 NUMA 节点上不存在的ZONE_HIGHMEM)。

调用场景

它主要被以下函数调用:

1.si_meminfo()/si_mem_available()

用于/proc/meminfo的MemFree等字段,统计从ZONE_NORMAL开始的空闲页。

2.__zone_watermark_ok()的某些变体

用于判断从某个 zone 开始的空闲页是否满足水位。

3. 内存热插拔 / 回收决策

判断高 zone 的空闲页是否足够。

与相关函数的关系

函数作用
nr_free_zone_pages(offset)统计从offset到最高 zone 的空闲页
nr_free_buffer_pages()nr_free_zone_pages(GFP_USER)的封装,统计用户可用页
zone_page_state(zone, NR_FREE_PAGES)单个 zone 的空闲页

总结

nr_free_zone_pages()是按 zone 范围统计空闲页的辅助函数:它遍历从offset指定的 zone 开始到最高 zone 的所有 populated zone,累加NR_FREE_PAGES,返回总空闲页数。它主要用于/proc/meminfo的统计和内存管理决策,是理解系统“有多少可用内存”的基础工具。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询