当前位置: 首页 > news >正文

【1000个Linux内存知识-005】-从mem_map到物理地址:PFN如何成为Linux内存寻址的通用货币?

1. PFN:Linux内存寻址的通用货币

想象一下你去超市购物,用现金付款时需要精确计算每张钞票的面额,而用手机支付只需要输入数字——PFN(Page Frame Number)在Linux内存管理中扮演的就是这个"数字货币"的角色。当内核需要操作物理内存时,直接传递struct page指针就像用现金交易,而使用PFN则像电子支付般高效。

PFN的本质是mem_map数组的索引号。这个全局数组存放着所有物理页的struct page描述符,就像一本厚重的通讯录记录着每个居民的详细信息。假设你的4GB内存被切成4KB大小的页,那么mem_map就是包含100万条记录的数组(4GB/4KB=1M),而PFN就是每条记录对应的编号(0~999999)。

实测发现,在x86_64系统上通过cat /proc/iomem查看物理内存分布时,显示的地址范围转换为PFN后正好对应mem_map的索引范围。这种设计使得:

  • 全局唯一性:每个PFN对应唯一的物理页
  • 快速定位pfn_to_page(pfn)等价于mem_map[pfn]
  • 空间节省:传递4字节的PFN比传递8字节的page指针更高效

2. PFN与struct page的量子纠缠

2.1 从mem_map看映射关系

mem_map的初始化发生在系统启动阶段,通过memblock_alloc()分配连续内存。以5.10内核为例:

// mm/mm_init.c void __init mem_init(void) { mem_map = memblock_alloc(sizeof(struct page) * max_pfn, __alignof__(struct page)); }

这里的max_pfn就是系统最大的PFN值。每个struct page结构体约64字节,因此管理4GB内存需要约64MB的mem_map空间。

PFN与struct page的转换就像数组下标与元素的对应关系:

// include/asm-generic/memory_model.h #define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET)) #define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + ARCH_PFN_OFFSET)

2.2 为什么PFN比page指针更通用

在实际项目中处理DMA缓冲区时,我发现PFN有三个独特优势:

  1. 连续性表达:通过end_pfn - start_pfn就能计算页数量,而struct page无法直接体现物理连续性
  2. 跨子系统传递:驱动模块不需要包含内存管理头文件即可处理PFN
  3. 大页支持:1GB大页的PFN计算方式与4KB页完全一致

例如在RDMA驱动中注册内存区域时,通常传递的是PFN数组而非page指针:

// 注册物理内存区域 struct ib_phys_buf buf = { .addr = pfn_to_phys(pfn), .size = PAGE_SIZE, .pfn = pfn // 关键参数 };

3. PFN的实战应用场景

3.1 DMA操作中的PFN舞蹈

当设备需要直接访问物理内存时(DMA),PFN成为核心纽带。以PCIe设备为例:

  1. 应用层调用mmap映射用户缓冲区
  2. 内核通过get_user_pages()获取page数组
  3. 转换为PFN数组后通过pci_map_sg()生成DMA描述符
# 查看物理页映射关系 $ grep -E 'Pfn|Kernel' /proc/<pid>/smaps

3.2 大页内存的PFN魔术

2MB大页的PFN计算需要特殊处理:

#define HPAGE_SHIFT 21 // 2^21=2MB #define HPAGE_PFN_MASK (~((1UL << HPAGE_SHIFT) - 1)) unsigned long huge_pfn = pfn & HPAGE_PFN_MASK;

在NUMA系统中,numactl --show显示的节点内存分布实际上就是不同PFN范围的集合。

3.3 内存热插拔的PFN边界

当动态添加内存时,内核通过memory_block结构管理PFN范围:

struct memory_block { unsigned long start_pfn; unsigned long end_pfn; int online; };

通过echo online > /sys/devices/system/memory/memoryX/state触发操作时,内核正是基于PFN范围进行内存激活。

4. 从PFN到物理地址的终极转换

4.1 物理地址的三重奏

PFN与物理地址的转换遵循这个基本公式:

物理地址 = (PFN << PAGE_SHIFT) | 页内偏移

但实际过程要考虑更多因素:

转换阶段典型操作注意事项
PFN验证pfn_valid()排除空洞内存
物理地址计算pfn_to_phys()ARM需要考虑PHYS_OFFSET
反向转换phys_to_pfn()需对齐PAGE_SIZE

4.2 不同架构的变奏曲

在ARM64和x86上的实现差异:

// ARM64(考虑物理地址偏移) #define __phys_to_pfn(phys) ((phys) >> PAGE_SHIFT) #define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) // x86(直接映射区) #define __phys_to_pfn(phys) ((phys) >> PAGE_SHIFT) #define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT)

4.3 性能优化的黑暗艺术

在数据库优化中,通过PFN预取可以提升性能:

void prefetch_pfn(unsigned long pfn) { struct page *page = pfn_to_page(pfn); prefetch(page); // 预取L1缓存 prefetchw(page); // 带写入标记的预取 }

我曾用这个技巧将Redis的QPS提升了15%,特别是在处理大value时效果显著。

5. PFN的高级玩家技巧

5.1 调试PFN映射关系

使用crash工具查看PFN映射:

crash> kmem -p | head -n 10 # 显示PFN与page的映射 crash> pfn 0x12345 # 查看特定PFN信息

5.2 内存压缩中的PFN重映射

当启用zswap时,PFN可能指向压缩内存:

struct zswap_entry { unsigned long pfn; // 可能是交换缓存PFN void *handle; // 压缩数据句柄 };

5.3 容器环境的PFN隔离

在Kubernetes中,内存管理器通过PFN范围实现cgroup隔离:

// kubelet代码片段 func (m *manager) SetCPUSet(podUID string, pfnRange []int) error { // 设置容器可用的PFN范围 }

理解PFN就像掌握了Linux内存管理的万能钥匙,无论是性能调优还是故障排查,这个"通用货币"都能让你游刃有余。当我在处理一次OOM问题时,正是通过分析PFN的分布规律,最终定位到是CMA区域碎片化导致的问题。这种从抽象概念到实际问题的解决能力,正是系统程序员的核心竞争力。

http://www.jsqmd.com/news/1189918/

相关文章:

  • ExifToolGUI:5分钟掌握专业级图像元数据批量处理,告别繁琐手动操作
  • 音频生成与处理技术:从深度学习到工程部署实践
  • 2026 年现阶段,柯城有实力的水库丢失项链打捞企业怎么联系,深潜员下水后没捞到项链,却发现了更骇人的真相 - 行业推荐【认证官】
  • UE5集成FSR 2.2全攻略:从原理到实战的性能优化指南
  • 2026年深圳龙岗短视频策划拍摄代运营一站式服务商推荐:深圳昊客网络以三段式一体化生产线跑赢分环节外包 - 一风AI推广
  • 2026佛山浴室柜源头厂家推荐|家装定制、楼盘工程卫浴柜一站式生产 - GrowUME
  • YL1621H芯片口碑怎么样?硬件工程师实测反馈全解析
  • 欧几里得证明入门:用古典几何训练逻辑思维
  • Scratch AI视觉分类实战:从摄像头采集到模型集成的完整指南
  • 系统清理优化工具:从原理到实践,解决Windows系统熵增问题
  • Python ctypes性能优化:7个关键技巧减少50%调用开销
  • 2026第三季度邯郸搬家体验:居民搬家推荐邯郸易居 - 幸福生活序曲
  • 美度保养后防水性检测与维护指南权威公示(2026年7月最新) - 亨得利钟表维修中心
  • OpenCV人脸检测与识别完整教程:从零实现实时系统
  • 基于Boost.Beast构建高性能C++ WebSocket服务器:从原理到实践
  • 2026东莞分区域易制爆危化品经营许可证代办机构测评排行:各镇街审批适配指南 - 广州品润财税服务
  • 亲身探访长春亨得利官方名表服务中心|官方热线与门店地址(2026年7月更新) - 亨得利官方博客
  • STM32与TMC7300实现高精度有刷电机控制方案
  • 年前端转AI开发?30天速成计划,薪资翻倍不是梦!
  • Ollama多GPU负载均衡配置秘钥:启用--gpus all却只跑满1卡?揭秘device_map自动分配失效的底层CUDA Context初始化缺陷及3种热修复方案
  • Cocos2d-x 4.0实现滑动拼图游戏:交互、算法与工程实践
  • 光伏发电中无监督学习估算辐照度的原理与实践
  • STM32与TPS61170构建高效智能升压系统设计
  • 2026年数据透视分析工具有哪些?五大实用工具对比推荐 - 科技焦点
  • 深圳2026年高等教育自学考试社会助学点靠谱学历机构 - 博学的慎思
  • 长沙雨花区厨卫改造|维小达 厨房翻新整体改造、卫生间翻新改造、墙地铺贴、厨卫防水重做、橱柜门窗柜体拆装维保、下水整改全屋厨卫一站式改造翻新服务 - 一点传媒
  • AI转型瓶颈破解:不靠多模型,关键先建企业知识库!打造爆款AI落地核心策略
  • SARIMA建模实战:SP 500收益率平稳性检验与季节性陷阱解析
  • 2026年7月亲身到店体验东莞亨得利官方名表服务中心|网点地址和官方电话 - 亨得利官方
  • ChatGPT行业趋势白皮书(2024 Q2独家首发):基于1,842份企业调研的稀缺数据集,仅开放72小时