[TOC]

mm\vmstat.c

init_mm_internals

  • 初始化内存管理(MM)子系统中,那些依赖于其他核心子系统(如workqueue、cpuhp)已经建立的、更深层次的内部组件。
    它并非内存管理的最早期初始化(如物理页帧分配器的建立),而是一个第二阶段的、功能性的初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* 这是一个静态的、仅在初始化阶段调用的函数,负责初始化内存管理(MM)的内部组件。
*/
void __init init_mm_internals(void)
{
/* ret: 用于接收函数返回值,__maybe_unused属性告诉编译器,在某些配置下
* (如非SMP),这个变量可能未被使用,不要因此产生警告。*/
int ret __maybe_unused;

/*
* 为MM子系统分配一个名为"mm_percpu_wq"的工作队列。
* WQ_MEM_RECLAIM标志非常重要,它告诉workqueue系统,这个队列中的工作者
* 在内存回收时具有特殊的分配权限,以防止在内存回收路径上发生死锁。
*/
mm_percpu_wq = alloc_workqueue("mm_percpu_wq", WQ_MEM_RECLAIM, 0);

/* 如果内核配置了对称多处理(SMP)支持。*/
#ifdef CONFIG_SMP
/*
* 向CPU热插拔(cpuhp)框架注册一个状态回调,用于处理CPU死亡事件。
* 当CPU进入CPUHP_MM_VMSTAT_DEAD状态时,vmstat_cpu_dead函数将被调用。
*/
ret = cpuhp_setup_state_nocalls(CPUHP_MM_VMSTAT_DEAD, "mm/vmstat:dead",
NULL, vmstat_cpu_dead);
/* 如果注册失败,打印错误信息。*/
if (ret < 0)
pr_err("vmstat: failed to register 'dead' hotplug state\n");

/*
* 向CPU热插拔框架注册另一个状态回调,用于处理CPU上线和下线准备事件。
* 当CPU进入CPUHP_AP_ONLINE_DYN状态时,vmstat_cpu_online将被调用。
* 当CPU退出该状态(即准备下线)时,vmstat_cpu_down_prep将被调用。
*/
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "mm/vmstat:online",
vmstat_cpu_online,
vmstat_cpu_down_prep);
/* 如果注册失败,打印错误信息。*/
if (ret < 0)
pr_err("vmstat: failed to register 'online' hotplug state\n");

/* 获取cpus_lock的读锁,以安全地访问CPU拓扑信息。*/
cpus_read_lock();
/* 初始化每个CPU与其NUMA节点相关的状态。*/
init_cpu_node_state();
/* 释放读锁。*/
cpus_read_unlock();

/* 启动“牧羊人”定时器,用于周期性的NUMA内存平衡。*/
start_shepherd_timer();
#endif
/* 如果内核配置了proc文件系统支持。*/
#ifdef CONFIG_PROC_FS
/* 在/proc下创建buddyinfo文件,提供伙伴系统碎片化信息。*/
proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op);
/* 在/proc下创建pagetypeinfo文件,提供页面迁移类型信息。*/
proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op);
/* 在/proc下创建vmstat文件,提供详细的虚拟机统计信息。*/
proc_create_seq("vmstat", 0444, NULL, &vmstat_op);
/* 在/proc下创建zoneinfo文件,提供每个内存域的详细信息。*/
proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op);
/* 在sysctl中注册一组可动态调整的VM参数(位于/proc/sys/vm/)。*/
register_sysctl_init("vm", vmstat_table);
#endif
}