为什么内存管理器使用 (size + PAGE_SIZE-1) / PAGE_SIZE 来计算要分配的页数?

Why do memory managers use (size + PAGE_SIZE-1) / PAGE_SIZE to calculate the number of pages to allocate?

我在不同的地方多次遇到这样的公式(例如;Linux kernel 和 glibc)。为什么他们使用这个公式而不是简单地:

pages = (size / PAGE_SIZE) + 1;

作为一个猜测,我认为上面公式的问题是当大小 PAGE_SIZE 对齐(PAGE_SIZE 的倍数)时,因为在这种情况下,它会报告多一页超出需要,因此我们还必须这样做:

pages = (size / PAGE_SIZE) + 1;
if (!(size & (PAGE_SIZE-1))) /* is size a multiple of PAGE_SIZE? */
    pages--;

这显然比 (size + PAGE_SIZE-1) / PAGE_SIZE!

更多的代码

是的,用于取除法结果的上限,即商向上取整

的问题
pages = (size / PAGE_SIZE) + 1;
if (!(size & (PAGE_SIZE-1))) /* is size a multiple of PAGE_SIZE? */
    pages--;

不仅代码多了很多,而且

  • 由于分支
  • ,它的性能更差
  • 它只适用于 2 的幂

当然,二进制计算机中的页面大小始终是 2 的幂,但是 (size + PAGE_SIZE-1) / PAGE_SIZE 适用于除数的任何值

另见

  • Fast ceiling of an integer division in C / C++
  • Rounding integer division (instead of truncating)
  • Dividing two integers and rounding up the result, without using floating point
  • What's the right way to implement integer division-rounding-up?

这是四舍五入。您将 (PAGE_SIZE - 1) 添加到 nbytes 所以如果您有 PAGE_SIZE nbytes 的确切数量,那么您将获得所需的最少页数,如果您将它传递给一个,然后你会得到一个新页面,为额外的字节提供 space。

还有一种方法是用log2的页面大小。在Linux内核源码中,是PAGE_SHIFT。例如,如果 PAGE_SIZE 为 4096 = 2^12 字节,则 PAGE_SHIFT 为 12(即 log2(2^ 12)).因此,要获得给定 sizepages 的数量,通常使用以下公式:

页数 = (大小 + PAGE_SIZE - 1) >> PAGE_SHIFT

顺便说一下,页面大小通常定义为:

#define PAGE_SIZE (1 << PAGE_SHIFT)