Stone's Blog

nginx内存对齐

最近在看Nginx的源代码,阅读其有关内存池实现的时候发现下面一段代码

1
2
3
if (align) {
m = ngx_align_ptr(m, NGX_ALIGNMENT);
}

这段代码的意图很明显,就是将指针m按照NGX_ALIGNMENT大小进行对齐,那么它是如何进行对齐的呢?关键就在ngx_align_ptr,它其实是个宏,定义如下:

1
2
#define ngx_align_ptr(p, a) \
(u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))

我刚看到这个宏的时候觉得很神奇,完全不知道它进行内存对齐的原理是什么。于是打算人肉运行一下这段代码,看能不能发现里面的玄机。

首先类型转换都去掉,这样代码能看的清楚一点:

1
(p + (a - 1)) & ~(a-1)

在进行内存的对齐的时候,一般都是将地址按2的幂进行对齐,也就是说a的末尾必然由0组成。假设有N个0,那么将a减去一后,就得到了一个末尾有N1其他位都是0的数,再取反的话就变成了末尾有N个0,其他位都是1的数。那么再将这个数与任何数相与都将把被与数的最后N位变成0而其他位置不变,而这个数正是a的整数倍。那么加上a-1的目的是什么呢?很明显是为了最后得到的数要比p大,不然后的话,分配的内存就可能占用了别的已分配空间。

另外上面在进行运算之前将所有的变量都转换成了uintptr_t类型,该类型本质上也是个整型,但是该整型的大小能够安全的容纳指针变量,相比于直接用整数类型而言更加具有可移植性和安全性。

(完)