问题
I came across following algorithm that aligns virtual address to immediate next page bounday.
VirtualAddr = (VirtualAddr & ~(PageSize-1));
Also, given a length of bytes aligns length (rounds it) to be on the page boundary
len = ((PageSize-1)&len) ? ((len+PageSize) & ~(PageSize-1)):len;
I am finding it hard to decipher how this works. Can someone help me out to break it down?
回答1:
Those calculations assume that the page size is a power of 2 (which is the case for all systems that I know of), for example
PageSize = 4096 = 2^12 = 1000000000000 (binary)
Then (written as binary numbers)
PageSize-1 = 00...00111111111111
~(PageSize-1) = 11...11000000000000
which means that
(VirtualAddr & ~(PageSize-1))
is VirtualAddr
with the lower 12 bits set to zero or, in other words,
VirtualAddr
rounded down to the next multiple of 2^12 = PageSize
.
Now you can (hopefully) see that in
len = ((PageSize-1)&len) ? ((len+PageSize) & ~(PageSize-1)):len;
the first expression
((PageSize-1)&len)
is zero exactly if len
is a multiple of PageSize
. In that case, len
is left
unchanged. Otherwise (len + PageSize)
is rounded down to the next multiple of
PageSize
.
So in any case, len
is rounded up to the next multiple of PageSize
.
回答2:
I think the first one should be
VirtualAddr = (VirtualAddr & ~(PageSize-1)) + PageSize;
回答3:
This one-liner will do it - if it is already aligned aligned it will not skip to the next page boundary:
aligned = ((unsigned long) a & (getpagesize()-1)) ? (void *) (((unsigned long) a+getpagesize()) & ~(getpagesize()-1)) : a;
This one-liner will do it - if it is already aligned aligned it will not skip to the next page boundary:
if you really do want to skip to the next page boundary even if it's already aligned - just do:
aligned = (void *) (((unsigned long) a+getpagesize()) & ~(getpagesize()-1))
This should avoid all compiler warnings, too.
getpagesize()
is a POSIX thing. #include <unistd.h>
to avoid warnings.
来源:https://stackoverflow.com/questions/22970621/aligning-virtual-address-to-immediate-next-page-boundary