我遇到了以下算法,它将虚拟地址与紧邻的下一页界限对齐。
VirtualAddr = (VirtualAddr & ~(PageSize-1));
此外,给定一个字节长度将长度(将其舍入)对齐在页面边界上
len = ((PageSize-1)&len) ? ((len+PageSize) & ~(PageSize-1)):len;
我发现很难破译它是如何工作的。 有人可以帮我分解吗?
答案 0 :(得分:7)
这些计算假设页面大小是 2的幂(情况就是如此) 我所知道的所有系统,例如
PageSize = 4096 = 2^12 = 1000000000000 (binary)
然后(写成二进制数字)
PageSize-1 = 00...00111111111111
~(PageSize-1) = 11...11000000000000
这意味着
(VirtualAddr & ~(PageSize-1))
是VirtualAddr
,低12位设置为零,换句话说,
VirtualAddr
将向下舍入到2^12 = PageSize
的下一个倍数。
现在你可以(希望)在
中看到它len = ((PageSize-1)&len) ? ((len+PageSize) & ~(PageSize-1)):len;
第一个表达
((PageSize-1)&len)
如果len
是PageSize
的倍数,则为零。在这种情况下,剩下len
不变。否则(len + PageSize)
向下舍入到下一个倍数
PageSize
。
因此,无论如何,len
将向上舍入到PageSize
的下一个倍数。
答案 1 :(得分:2)
我认为第一个应该是
VirtualAddr = (VirtualAddr & ~(PageSize-1)) + PageSize;
答案 2 :(得分:0)
这个单行将会这样做 - 如果它已经对齐,它将不跳到下一页边界:
aligned = ((unsigned long) a & (getpagesize()-1)) ? (void *) (((unsigned long) a+getpagesize()) & ~(getpagesize()-1)) : a;
这个单行将会这样做 - 如果它已经对齐,它将不跳到下一页边界:
如果你真的做想要跳到下一页边界,即使它已经对齐 - 只需这样做:
aligned = (void *) (((unsigned long) a+getpagesize()) & ~(getpagesize()-1))
这应该避免所有编译器警告。
getpagesize()
是一个POSIX的东西。 #include <unistd.h>
以避免警告。