☰
math PFN_UP
2026/9/25 4:28:39 网站建设 项目流程

PFN_UP是PFN_DOWN的配套宏,用于将物理地址向上取整转换为页帧号(PFN)。定义在include/linux/pfn.h中。

定义与原理

#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)

它的核心逻辑是先将地址加上PAGE_SIZE - 1,再右移PAGE_SHIFT位,相当于向上取整除法。

在 x86 架构下,PAGE_SHIFT为 12,PAGE_SIZE为 4096,因此:

PFN_UP(addr) = (addr + 4095) / 4096

核心作用

将物理地址向上取整到它所在的下一个页帧号。如果地址恰好落在页边界上,则返回该页的页帧号;否则返回下一页的页帧号。

表达式结果说明
PFN_UP(0)0恰好是页边界,返回第 0 页
PFN_UP(1)1跨越了第 0 页,向上取整到第 1 页
PFN_UP(4095)1仍在第 0 页内,向上取整到第 1 页
PFN_UP(4096)1恰好是页边界,返回第 1 页
PFN_UP(4097)2跨越了第 1 页,向上取整到第 2 页

与PFN_DOWN的对比

宏行为示例
PFN_DOWN(x)向下取整,返回地址所在页的 PFNPFN_DOWN(4095) = 0
PFN_UP(x)向上取整,返回地址之后的页的 PFNPFN_UP(4095) = 1

两者的关系可以用一个不等式表示:

PFN_DOWN(addr) <= PFN_UP(addr)

内核中的典型用途

PFN_UP最常见的场景是计算一段内存区域跨越的页数,尤其是当起始或结束地址不在页边界上时:

  1. 计算覆盖某段内存所需的页数:

    nr_pages = PFN_UP(end) - PFN_DOWN(start);
  2. 确保分配的内存覆盖请求范围:
    如果请求的大小不是页大小的整数倍,PFN_UP会确保分配的页数足够覆盖整个请求。

  3. DMA 缓冲区计算:
    设备 DMA 操作通常要求缓冲区按页对齐,PFN_UP用于确定实际需要映射的页数。

使用注意

  • PFN_UP是向上取整,意味着即使地址只多出 1 字节,也会算作新的一页。

  • 该宏假设输入是物理地址,不适用于虚拟地址。

  • 在计算页数时,通常需要PFN_UP(end) - PFN_DOWN(start),而不是简单的PFN_UP(end) - PFN_UP(start),否则可能少算一页。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询