
AI-摘要
Tianli GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
[linux内存管理] 第014篇 /proc/zoneinfo的详细解析
iliuqi0. 前言
内存管理是一个相对复杂的内核模块,错综复杂的 数据结构 和管理逻辑。 Linux 内核为了帮助开发者从宏观上把握内存的使用情况,在几大核心数据结构中都有相应的计数统计,如物理页面使用情况、伙伴系统分配情况、内存管理区的页面使用情况、内存回收扫描回收情况、内存规整触发情况等等。
在 start_kernel()
中,会通过 setup_arch()
、 build_all_zonelists()
、 page_alloc_init()
、 mm_init()
等函数对内存相关模块进行初始化,最后会通过 arch_call_rest_init()
对 Linux 系统做剩余的初始化工作,此函数中会调用 rest_init()
,并在此调用 kernel_init()
启动init 线程,这里创建了本文将要剖析的虚拟文件节点 /proc/zoneinfo 。
1. zoneinfo_show
1 | static int zoneinfo_show(struct seq_file *m, void *arg) |
调用 zoneinfo_show() 时,会通过函数 walk_zones_in_node() 对每个zone 进行遍历,从第 0 个zone 开始,当参数 zone 为第 0 个 zone 且该zone 的 present_pages 不为0 时, is_zone_first_populated () 返回为 true,则会将该 node 的page 信息打印出来。
2. zoneinfo_show_print
1 | static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, |
该函数大致分下面几个部分剖析:
- 第一次调用时,输出当前 node 的内存统计信息,记录在 vm_node_stat 数组中,见 2.1 节;
- 输出 zone 的总信息,见 2.2 节;
- 输出 zone 的详细页面信息,记录在 zone->vm_stat 数组中,见 2.3 节;
- 输出 zone 的 pageset 信息,即zone 在每个 CPU 内存分配器信息,记录在 zone->pageset 链表中,见 2.4 节;
- 输出 zone 回收的 kswapd_failures 是否大于 MAX_RECLAIM_RETRIES(16) ,见 2.5节;
- 输出 zone 的start_pfn,见 2.5 节;
2.1 输出当前node的内存统计信息
1 | Node 0, zone Normal |
参数解释:
参数名称 | 含义 |
---|---|
nr_inactive_anon | 非活跃的匿名页面数(以页为单位)。匿名页面通常与进程的私有内存相关,这些页面可能成为回收目标。 |
nr_active_anon | 活跃的匿名页面数(以页为单位)。活跃页面通常在频繁使用,优先保留,不会立即回收。 |
nr_inactive_file | 非活跃的文件缓存页面数(以页为单位)。这些页面存储文件数据但使用频率低,可能成为回收目标。 |
nr_active_file | 活跃的文件缓存页面数(以页为单位)。这些页面存储文件数据且使用频率高,不容易被回收。 |
nr_unevictable | 无法驱逐的页面数,通常被锁定(如通过 mlock)。这些页面不能被回收。 |
nr_slab_reclaimable | 可回收的 slab 缓存页面数(以页为单位)。这些缓存可以在内存不足时被释放。 |
nr_slab_unreclaimable | 不可回收的 slab 缓存页面数(以页为单位)。这些缓存用于内核关键结构,不能被释放。 |
nr_isolated_anon | 正在隔离的匿名页面数(以页为单位)。用于内存回收时暂时从匿名页面中隔离的页面数量。 |
nr_isolated_file | 正在隔离的文件缓存页面数(以页为单位)。用于内存回收时暂时从文件缓存中隔离的页面数量。 |
workingset_nodes | 工作集的节点数,表示访问过的内存节点数量,用于评估内存活跃性。 |
workingset_refault_anon | 匿名页面在工作集中重新加载的次数。表示曾经被回收的匿名页面再次被访问的频率。 |
workingset_refault_file | 文件缓存页面在工作集中重新加载的次数。表示曾经被回收的文件缓存页面再次被访问的频率。 |
workingset_activate_anon | 被激活的匿名页面数,表明非活跃匿名页面被重新标记为活跃页面的次数。 |
workingset_activate_file | 被激活的文件缓存页面数,表明非活跃文件页面被重新标记为活跃页面的次数。 |
workingset_restore_anon | 恢复的匿名页面数,表示曾被回收的匿名页面被重新使用的次数。 |
workingset_restore_file | 恢复的文件缓存页面数,表示曾被回收的文件页面被重新使用的次数。 |
workingset_nodereclaim | 节点回收失败的次数,表示由于 NUMA 策略或内存不足而无法完成页面迁移的情况。 |
nr_anon_pages | 匿名页面的总数,包含活跃和非活跃的匿名页面。 |
nr_mapped | 映射到用户空间的页面数,通常是由 mmap 映射的页面。 |
nr_file_pages | 文件缓存页面的总数,包含活跃和非活跃的文件页面。 |
nr_dirty | 脏页面的数量,这些页面修改过但尚未写回磁盘。 |
nr_writeback | 正在写回的页面数,这些页面正从内存同步到磁盘。 |
nr_writeback_temp | 临时写回页面数,通常用于短期写回操作。 |
nr_shmem | 共享内存页面数,用于进程间共享的匿名内存。 |
nr_shmem_hugepages | 共享内存中使用的大页数量(以页为单位)。 |
nr_shmem_pmdmapped | 共享内存中通过 PMD 映射的大页数量(以页为单位)。 |
nr_file_hugepages | 文件缓存中使用的大页数量(以页为单位)。 |
nr_file_pmdmapped | 文件缓存中通过 PMD 映射的大页数量(以页为单位)。 |
nr_anon_transparent_hugepages | 匿名内存中透明大页的数量。 |
nr_vmscan_write | 内存扫描期间写回的页面数,通常在内存回收时触发。 |
nr_vmscan_immediate_reclaim | 内存扫描期间立即回收的页面数。 |
nr_dirtied | 被标记为脏的页面总数(历史累计值)。 |
nr_written | 写回磁盘的页面总数(历史累计值)。 |
nr_kernel_misc_reclaimable | 内核中其他可回收的页面数。 |
nr_foll_pin_acquired | 通过 get_user_pages() 获取的页面数。 |
nr_foll_pin_released | 通过 put_page() 释放的页面数。 |
nr_kernel_stack | 用于内核堆栈的页面数。 |
nr_shadow_call_stack | 用于影子调用堆栈的页面数(通常与硬件支持的功能相关)。 |
2.2 输出zone的总信息
1 | pages free 30498 |
参数解释:
字段名称 | 值 | 含义 |
---|---|---|
pages free |
30498 | 当前分区中空闲的页面数(以页为单位)。表示可以直接分配的内存大小,30498页约为30498×4KB = 119.1MB。 |
min |
2048 | 区域的最低水位线(以页为单位)。当pages free 低于此值时,系统会触发紧急内存回收。 |
low |
6047 | 区域的低水位线(以页为单位)。当pages free 低于此值时,系统会优先触发后台内存回收。 |
high |
6559 | 区域的高水位线(以页为单位)。当pages free 高于此值时,系统会停止内存回收。 |
spanned |
8381632 | 当前区域所覆盖的页面数(以页为单位),包括物理内存和可能存在的地址空洞。8381632 页约为8381632×4KB= 33,526,528KB = 31.9GB。 |
present |
930287 | 此分区中实际存在的物理页面数(以页为单位),即物理内存中属于该分区的页面总数。930287 页约为930287×4KB=3,721,148KB =3.55GB。 |
managed |
894377 | 此分区中受内核管理的页面数(以页为单位),即可供分配或回收的内存。894377 页约为894377×4KB=3,577,508 KB=3.41GB。 |
cma |
38912 | 为连续内存分配器(CMA)预留的页面数(以页为单位)。38912 页约为38912×4KB=155,648KB=152MB。 |
protection |
(0, 0, 0) | 保护值数组,用于描述区域间的内存保护机制。此处值为 (0, 0, 0),表明没有额外的内存保护设置。 |
2.3 输出 zone 的详细页面信息
1 | nr_free_pages 30498 |
参数名称 | 值 | 含义 |
---|---|---|
nr_free_pages |
30498 | 当前区域中空闲的页面数,表示可以直接分配的页面数量。30498 页约为30498×4KB=121,992KB=119.1MB。 |
nr_zone_inactive_anon |
122141 | 区域内非活跃的匿名页面数(以页为单位)。匿名页面通常与进程的私有内存相关,这些页面可能会被回收。 |
nr_zone_active_anon |
58839 | 区域内活跃的匿名页面数(以页为单位)。活跃的匿名页面通常在使用中,不容易被回收。 |
nr_zone_inactive_file |
189638 | 区域内非活跃的文件缓存页面数(以页为单位)。这些页面存储文件数据但使用频率低,可能成为回收目标。 |
nr_zone_active_file |
208381 | 区域内活跃的文件缓存页面数(以页为单位)。这些页面存储文件数据且使用频率高,不容易被回收。 |
nr_zone_unevictable |
26959 | 区域内无法回收的页面数(以页为单位)。通常是通过mlock 锁定的内存或某些内核专用页面。 |
nr_zone_write_pending |
12 | 区域内待写回的页面数(以页为单位)。这些页面已被标记为脏页,等待写回磁盘。 |
nr_mlock |
16525 | 被mlock 系统调用锁定的页面数(以页为单位)。这些页面被固定在内存中,防止被回收。 |
nr_page_table_pages |
22903 | 用于存储页表的页面数(以页为单位)。页表记录了虚拟地址和物理地址的映射关系,通常随进程数量增加而增加。 |
nr_bounce |
0 | 用于 I/O 操作的中转页面数(以页为单位)。这些页面用于支持不直接访问高地址的 DMA 设备,此处为 0 表明未使用中转页面。 |
nr_zspages |
53155 | 压缩页的总数(以页为单位)。压缩页是zswap 或zram 等机制压缩后的页面数,能够节省内存空间。 |
nr_free_cma |
0 | 连续内存分配器(CMA)中空闲的页面数(以页为单位)。此处为 0 表示预留的 CMA 内存已经全部分配或尚未启用。 |
2.4 输出 zone 的 pageset 信息
1 | pagesets |
参数解释:
参数名称 | 含义 |
---|---|
cpu |
表示具体的 CPU 编号,pagesets 为每个 CPU 维护独立的页面分配状态。 |
count |
表示当前 CPU 页面分配缓存中可用的页面数(以页为单位)。用于快速分配页面,减少全局锁的开销。 |
high |
页面缓存的高水位线,超过该值时,内核会将多余的页面返还到全局空闲页面池。 |
batch |
页面批量分配的大小,页面缓存中每次从全局池中获取或释放的页面数。 |
vm stats threshold |
表示更新虚拟内存统计数据的阈值,当页面的变化量超过该值时,会触发统计更新(优化性能)。 |
2.5 其余信息
1 | node_unreclaimable: 0 |
参数解释:
参数名称 | 值 | 含义 |
---|---|---|
node_unreclaimable |
0 | 当前节点是否不可回收的标志位。值为 0 表示当前节点中的页面可以被回收,没有被标记为不可回收。 |
start_pfn |
525888 | 当前节点的起始页帧号(PFN, Page Frame Number)。用于指示该节点的物理内存起始地址,单位为页(4KB)。 |
评论
匿名评论隐私政策