NGINX 内存池 — 对齐

在看 Nginx 内存池实现的时候,在 ngx_slab_init 函数的实现中最后有一个内存对齐的操作:

 pool->start = (u_char *) ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t), ngx_pagesize); 

其中p是指针,ngx_pagesize是页的大小,该操作就是向前移动p使其是ngx_pagesize的整数倍,ngx_align_ptr实现如下:

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

这段代码着实迷惑了我一下,想了半天,才发现自己在知识的运用上还是太生疏了:

  1. 内存页都是 2 的幂,如 x86 的页是就是 4096( 即2 ^ 12,即0b1000000000000
  2. 指针是无符号数
  3. 于是问题就变成了将一个无符号整数“上调”到最近的 2 的幂(4096)的倍数

分析到这里,一下了就想到了一本神书“Hacker’s Delight”(中文译作《高效算法的奥秘》),拿来一看第三章说的恰恰是这个问题!这本书在读研究生时在图书馆看过,但是只当时觉得神奇,看完了除了能“装”一下也不知道有什么用处,而“装”这个事在软件工程中总是不被提倡的,所以看了前几章也就放下了,今天终于“啊哈!”了一下。

对于上面宏中的pa(总是 0b10000 这样的形式),先看看下调:p & -a,其实就是把p后面和a中后面 0 同样多的的位置 0,也就是p & ~(a-1)

有了下调,上调就简单了,只要对p+(a-1)下调即可,即(p+(a-1)) & ~(a-1),这就是ngx_align_ptr的内容了。

 

总结:

  1. 知识总不嫌多,看不到实际应用是因为学识还不够
  2. 可以不记住所有细节,但是用时一定会记起出处
  3. 写点注释能死啊!
THE END