在浏览一些内核代码时,我发现内存对齐的公式为
aligned =((操作数+(对齐 - 1))&〜(对齐 - 1))
那么我甚至为此写了一个程序:
#include <stdio.h>
int main(int argc, char** argv) {
long long operand;
long long alignment;
if(argv[1]) {
operand = atol(argv[1]);
} else {
printf("Enter value to be aligned!\n");
return -1;
}
if(argv[2]) {
alignment = strtol(argv[2],NULL,16);
} else {
printf("\nDefaulting to 1MB alignment\n");
alignment = 0x100000;
}
long long aligned = ((operand + (alignment - 1)) & ~(alignment - 1));
printf("Aligned memory is: 0x%.8llx [Hex] <--> %lld\n",aligned,aligned);
return 0;
}
但我根本就没有这个逻辑。这是如何工作的?
答案 0 :(得分:1)
基本上,公式会将整数operand
(地址)增加到与alignment
对齐的下一个地址。
表达式
aligned = ((operand + (alignment - 1)) & ~(alignment - 1))
基本上与更容易理解的公式相同:
aligned = int((operand + (alignment - 1)) / alignment) * alignment
例如,我们得到操作数(地址)102和对齐10:
aligned = int((102 + 9) / 10) * 10
aligned = int(111 / 10) * 10
aligned = 11 * 10
aligned = 110
首先,我们添加到地址9
并获取111
。然后,由于我们的对齐是10,基本上我们将最后一位数字归零,即111 / 10 * 10 = 110
请注意,对于每个10对齐的功率(即10,100,1000等),我们基本上将最后的数字归零。
在大多数CPU上,除法和乘法运算比按位运算花费的时间要多得多,所以让我们回到原来的公式:
aligned = ((operand + (alignment - 1)) & ~(alignment - 1))
只有当对齐是2的幂时,公式的第二部分才有意义。例如:
... & ~(2 - 1) will zero last bit of address.
... & ~(64 - 1) will zero last 5 bits of address.
etc
就像将10个对齐功率的地址的最后几位归零一样,我们将最后几位归零以获得2个对齐的功率。
希望现在对你有意义。