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

问题描述

我在不同的地方(例如 Linux 内核和 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更多的代码

解决方法

是的,用于得到除法结果的上限,即对商进行四舍五入

问题

(size + PAGE_SIZE-1) / PAGE_SIZE

不仅是更多的代码,而且还有

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

当然,二进制计算机中的页面大小总是 2 的幂,但 {{1}} 适用于除数的任何值

另见

,

这是四舍五入。您将 (PAGE_SIZE - 1) 添加到 nbytes 以便如果您有PAGE_SIZE nbytes 的确切数量,那么您将获得所需的最少页数,如果您通过一个,然后你会得到一个新页面,为额外的字节留出空间。

,

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

pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT

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

#define PAGE_SIZE (1 PAGE_SHIFT)