ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

page_alloc min_free_kbytes_sysctl_handler

page_alloc min_free_kbytes_sysctl_handler

min_free_kbytes_sysctl_handler()是/proc/sys/vm/min_free_kbytes的 sysctl 处理函数,负责响应用户对该参数的读写请求。

核心实现

static int min_free_kbytes_sysctl_handler(const struct ctl_table *table, int write, void *buffer, size_t *length, loff_t *ppos) { int rc; rc = proc_dointvec_minmax(table, write, buffer, length, ppos); if (rc) return rc; if (write) { user_min_free_kbytes = min_free_kbytes; setup_per_zone_wmarks(); } return 0; }

逐步解析

1. 委托标准整数读写

rc = proc_dointvec_minmax(table, write, buffer, length, ppos); if (rc) return rc;
  • proc_dointvec_minmax():标准 sysctl 整数处理函数,负责把用户输入的字符串解析为整数并写入table->data(即min_free_kbytes),或把当前值读出给用户。

  • 带_minmax后缀表示它在写入时会检查值是否在table->extra1(最小值)和table->extra2(最大值)范围内。

  • 如果解析或范围检查失败,直接返回错误。

2. 写操作后的额外处理

if (write) { user_min_free_kbytes = min_free_kbytes; setup_per_zone_wmarks(); }

只有写操作才需要:

  • user_min_free_kbytes = min_free_kbytes:记录用户显式设置的值。user_min_free_kbytes初始为-1,用于区分"用户未设置"和"用户设置了某个值"。这里把它更新为当前值,以便后续calculate_min_free_kbytes()知道用户已经有明确设置,不应被自动计算覆盖。

  • setup_per_zone_wmarks():min_free_kbytes变了,必须重新计算所有 zone 的WMARK_MIN/WMARK_LOW/WMARK_HIGH。这个调用会获取pcp_batch_high_lock并调用__setup_per_zone_wmarks()。

3. 读操作

如果write == 0,函数只执行proc_dointvec_minmax()把当前min_free_kbytes值复制到用户缓冲区,不做额外处理。

sysctl 表定义

这个 handler 通常注册在vm_table[]中:

{ .procname = "min_free_kbytes", .data = &min_free_kbytes, .maxlen = sizeof(min_free_kbytes), .mode = 0644, .proc_handler = min_free_kbytes_sysctl_handler, .extra1 = SYSCTL_ZERO, },
  • .data指向全局min_free_kbytes;

  • .proc_handler是本函数;

  • .extra1设最小值 0(或某个下限)。

与相关函数的关系

函数职责
min_free_kbytes_sysctl_handler()sysctl 入口:读写min_free_kbytes,写时更新水位
proc_dointvec_minmax()标准整数读写
setup_per_zone_wmarks()重新计算各 zone 水位
user_min_free_kbytes记录用户显式设置值
calculate_min_free_kbytes()启动时自动计算默认值

历史演进

早期版本的 handler 在写操作后还会调用setup_per_zone_lowmem_reserve(),因为lowmem_reserve的计算也依赖managed_pages,而min_free_kbytes的变化可能间接影响它。但在现代内核中,lowmem_reserve的计算已独立,只在 zone 大小变化时更新,因此 handler 只调用setup_per_zone_wmarks()。

总结

min_free_kbytes_sysctl_handler()是vm.min_free_kbytes的sysctl 读写入口:它先通过proc_dointvec_minmax()完成标准的整数读写和范围检查,如果是写操作,则记录用户设置值到user_min_free_kbytes并调用setup_per_zone_wmarks()重新计算所有 zone 的水位线。它确保用户对最低保留内存的调整能立即生效,并防止被后续的自动计算覆盖。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进