资讯详情

page_alloc pfn_range_valid_contig

📅 2026/10/21 6:39:33 | 华诺云谱 👁 阅读
page_alloc pfn_range_valid_contig
pfn_range_valid_contig()是alloc_contig_pages()在扫描候选 PFN 范围时的“快速有效性检查”函数。它用于在真正尝试分配之前快速排除那些绝对不可能成功的范围避免无谓地调用开销巨大的alloc_contig_range()。核心作用快速筛掉“绝对不行”的范围alloc_contig_pages()会遍历 zonelist 中的每个 zone对每个对齐的候选起始 PFN 调用此函数。如果返回falsealloc_contig_pages()会跳过该范围继续尝试下一个。static bool pfn_range_valid_contig(struct zone *z, unsigned long start_pfn, unsigned long nr_pages) { unsigned long i, end_pfn start_pfn nr_pages; struct page *page; for (i start_pfn; i end_pfn; i) { page pfn_to_online_page(i); if (!page) return false; if (page_zone(page) ! z) return false; if (PageReserved(page)) return false; } return true; }三项核心检查1.pfn_to_online_page(i)— 页必须存在且在线如果 PFN 对应的页根本不存在内存空洞或未上线直接排除。这是最基础的检查确保后续操作不会访问无效的struct page。2.page_zone(page) ! z— 页必须属于目标 zone候选范围必须完全落在同一个 zone 内。如果跨越了 zone 边界排除该范围。3.PageReserved(page)— 页不能是保留页PageReserved的页如内核镜像、设备内存、BIOS 区域永远不能被迁移或分配。只要范围内有任何一页是保留页整个范围就不可能成功直接排除。关键演进2021 年移除的检查在 2021 年的补丁Oscar Salvador之前该函数还检查两项if (page_count(page) 0) // 页正在被使用 return false; if (PageHuge(page)) // 页是 hugetlb 页 return false;移除原因page_count(page) 0正在使用的页可以被__alloc_contig_pages()迁移走所以“正在使用”并不代表“不能分配”。预先排除反而会显著降低分配成功率错过那些本可通过迁移腾出的范围。PageHuge(page)isolate_migratepages_range()现在能够处理 hugetlb 页因此也不需要预先排除。更深层的原因这两项检查本身是有竞态的——检查时页可能空闲但alloc_contig_range()真正运行时可能已被占用反之亦然。既然终究要在alloc_contig_range()中处理不如信任底层函数的能力让pfn_range_valid_contig()只做那些绝对必要且无竞态的检查。在调用链中的位置alloc_contig_pages(nr_pages, gfp_mask, nid, nodemask) └── for_each_zone_zonelist_nodemask(zone, ...): ├── spin_lock_irqsave(zone-lock, flags) ├── pfn ALIGN(zone-zone_start_pfn, nr_pages) └── while (zone_spans_last_pfn(zone, pfn, nr_pages)): ├── if (pfn_range_valid_contig(zone, pfn, nr_pages)) // ← 这里 │ ├── spin_unlock_irqrestore(zone-lock, flags) │ └── __alloc_contig_pages(pfn, nr_pages, gfp_mask) └── pfn nr_pages注意pfn_range_valid_contig()是在持有zone-lock的情况下调用的用于快速筛选。一旦通过检查锁会被释放再调用__alloc_contig_pages()它内部会重新获取锁。注释解释了原因alloc_contig_range()稍后也会获取zone-lock如果一直持有可能导致锁竞争或死锁。总结pfn_range_valid_contig()是alloc_contig_pages()的快速预筛器它在持锁状态下遍历候选 PFN 范围只做三项绝对必要且无竞态的检查——页是否在线、是否属于目标 zone、是否为保留页。它不再检查页是否正在使用或是否为 hugetlb 页因为这些页可以被迁移预先排除会降低分配成功率且检查本身具有竞态。它的存在是为了低成本地过滤掉明显不可能的范围避免对它们执行昂贵的隔离和迁移操作。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑