ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

page_alloc zone_names

page_alloc zone_names zone_names[]——每个 zone 类型对应的人类可读名称字符串数组。它是 zone 的名字表用于打印、调试、/proc输出等。mcrjnjfbr一、作用与类型char * const zone_names[MAX_NR_ZONES] { ... };类型char * const [MAX_NR_ZONES]char *指向字符串的指针。const修饰指针本身数组元素指针不可修改即初始化后不能再让zone_names[i]指向别的字符串。指向的字符串内容是字面量本身就在只读段也不能改。维度MAX_NR_ZONES即系统支持的最大 zone 数量。索引用ZONE_DMA、ZONE_DMA32、ZONE_NORMAL……这些枚举值作为下标。值对应的名字字符串如DMA、Normal。核心用途根据 zone 索引快速拿到可打印的名字。printk(zone %s: ..., zone_names[zone_idx]);比如/proc/zoneinfo、/proc/buddyinfo、内存热插拔日志、OOM 报告等都会用到。二、逐项解析1.ZONE_DMA→DMA#ifdef CONFIG_ZONE_DMA DMA, #endif只在配置了CONFIG_ZONE_DMA的架构上存在。对应16MB 以下的 DMA 可用内存老式 ISA 设备。2.ZONE_DMA32→DMA32#ifdef CONFIG_ZONE_DMA32 DMA32, #endif只在配置了CONFIG_ZONE_DMA32的架构上存在典型是x86_64。对应4GB 以下、32 位设备可寻址的内存。3.ZONE_NORMAL→NormalNormal,无条件存在所有架构都有。内核可直接访问的普通内存是分配的主力。4.ZONE_HIGHMEM→HighMem#ifdef CONFIG_HIGHMEM HighMem, #endif只在 32 位架构如 x86_32、ARM 某些配置上存在。高端内存内核不能直接线性映射需kmap临时映射。5.ZONE_MOVABLE→MovableMovable,无条件存在现代内核。可移动内存 zone用于减少碎片、支持内存热插拔。用户态可移动页优先放这里便于规整/迁移。6.ZONE_DEVICE→Device#ifdef CONFIG_ZONE_DEVICE Device, #endif只在配置了CONFIG_ZONE_DEVICE时存在。对应设备内存如 GPU 显存、持久内存 PMEM、HMM 设备内存通过devm_memremap_pages()注册到内存管理。特殊这些页可能不对应真正的 RAM。三、为什么用指定初始化器注意这里没有写[ZONE_DMA] DMA而是按顺序列出char * const zone_names[MAX_NR_ZONES] { #ifdef CONFIG_ZONE_DMA DMA, // 对应 ZONE_DMA #endif #ifdef CONFIG_ZONE_DMA32 DMA32, // 对应 ZONE_DMA32 #endif Normal, // 对应 ZONE_NORMAL ... };这是顺序初始化依赖于zone 枚举的定义顺序与数组顺序严格一致。zone 枚举在include/linux/mmzone.h中定义顺序正是ZONE_DMA, ZONE_DMA32, ZONE_NORMAL, ZONE_HIGHMEM, ZONE_MOVABLE, ZONE_DEVICE, ...条件编译保证开启哪个 zone数组里就补上对应项顺序仍对齐。这是一种隐式约定如果枚举顺序改了这里也必须同步改否则名字会错位。对比前面的sysctl_lowmem_reserve_ratio[]用的是[ZONE_DMA] 256指定初始化器那种写法更安全不依赖顺序。而这里用顺序初始化可能是历史原因或为了简洁但维护时需要小心。四、与MAX_NR_ZONESMAX_NR_ZONES是 zone 类型的最大数量枚举总数编译期常量。数组大小必须 ≥ 实际 zone 数量。条件编译保证只有实际存在的 zone 才占数组项未定义项默认为NULL因为数组是静态存储未初始化元素为 0。所以zone_names[idx]对未编译进来的 zone 是NULL访问前应确保 idx 有效。五、典型使用场景1./proc/zoneinfo、/proc/buddyinfoNode 0, zone DMA Node 0, zone DMA32 Node 0, zone Normal这些名字就来自zone_names[]。2. 打印 zone 信息pr_info(Node %d, zone %s\n, nid, zone_names[zone_idx]);3. 内存热插拔 / OOM 报告热插拔日志会打印 zone 名。OOM killer 报告里也会显示 zone。4. 调试与追踪dump_page()、show_free_areas()等会用到。六、与前面内容的呼应前面出现过的这里的对应sysctl_lowmem_reserve_ratio[MAX_NR_ZONES]同样以 zone 枚举为索引ZONE_DMA/ZONE_DMA32/ZONE_NORMAL/ZONE_HIGHMEM/ZONE_MOVABLE这里的数组项一一对应CONFIG_ZONE_DEVICE新增的Device项MAX_NR_ZONES数组维度它们共同构成zone 维度的配置/名字表是 zone 相关代码的基础设施。七、小结表索引枚举名字条件含义ZONE_DMADMACONFIG_ZONE_DMA16MB 以下 DMA 内存ZONE_DMA32DMA32CONFIG_ZONE_DMA324GB 以下 32 位可寻址ZONE_NORMALNormal无条件内核可直接访问的普通内存ZONE_HIGHMEMHighMemCONFIG_HIGHMEM高端内存需 kmapZONE_MOVABLEMovable无条件可移动内存反碎片/热插拔ZONE_DEVICEDeviceCONFIG_ZONE_DEVICE设备内存GPU/PMEM/HMM一句话总结zone_names[]是 zone 索引到可读名称的映射表按 zone 枚举顺序用条件编译逐项填充供打印、/proc输出和调试使用它依赖枚举与数组顺序严格一致未编译进的 zone 项为NULL。
返回列表