在看内核代码时,总是出现AGLIN,只是知道对齐的意思,但具体怎么回事是不理解。在此总结一下。
linux/kernel.h
#define ALIGN(x, a)__ALIGN_KERNEL((x),
(a))
uapi/linux/kernel.h
#define __ALIGN_KERNEL(x, a)__ALIGN_KERNEL_MASK(x,
(typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask)(((x) + (mask))
& ~(mask))
上面代码中,typeof(x)表示取x的类型,如果x是int,则typeof(x)为int。
(typeof(x))(a)-1,表明把a转化为x的类型,并减1,作为对齐掩码。
不考虑类型,上述代码可以简化为如下:
#define ALIGN(x,a) (((x)+(a)-1)&~(a-1))
举个例子说明一下:
int
a;
int size = 8;
1000(bin)
计算a以size为倍数的下界数:
就让这个数(要计算的这个数)表示成二进制时,最后三位为0就可以达到这个目标。只要下面这个数与a进行"与运算"就可以了:
11111111 11111111 11111111
11111000
而上面这个数实际下就是 ~(size -
1),可以将该数称为size的对齐掩码size_mask.
计算a以size为倍数的上下界数:
#define alignment_down(a, size) (a &
(~(size-1))
)
#define alignment_up(a,
size) ((a+size-1)
& (~
(size-1)))
注:
上界数的计算方法,如果要求出比a大的是不是需要加上8就可以了?可是如果a本身就是8的倍数,这样加8不就错了吗,所以在a基础上加上(size
- 1),
然后与size的对齐掩码进行与运算.
例如:
a=0, size=8,
则alignment_down(a,size)=0,
alignment_up(a,size)=0.
a=6, size=8,
则alignment_down(a,size)=0,
alignment_up(a,size)=8.
a=8, size=8,
则alignment_down(a,size)=8,
alignment_up(a,size)=8.
a=14,
size=8,则alignment_down(a,size)=8,
alignment_up(a,size)=16.
注:size应当为2的n次方, 即2, 4, 8,
16, 32, 64, 128, 256, 1024, 2048, 4096 ...
#define
ALIGN(x,a)
(((x)+(a)-1)&~((a)-1))
就是以a为上界对齐的意思。举个例子4k页面边界的例子,即a=4096: 如果x = 3888;那么以上界对齐,执行结果就是4096。
如果x = 4096;结果是4096. 如果x = 4222;
则结果为8192.
另外还有一种以下界对齐的方式 #define ALIGN(x,a) ((x)&~(a-1)) 若x =
3888; 结果为0. 如果x = 4096;结果是4096. 如果x = 4222; 则结果为4096.
你可以把这两种方式理解为“上进”和“丢弃”。
参考:http://blog.csdn.net/reille/article/details/6329195