现在的位置: 首页 > 综合 > 正文

MySQL中的ALIGN_SIZE宏解释

2014年02月06日 ⁄ 综合 ⁄ 共 2072字 ⁄ 字号 评论关闭

   在看MySQL的内存池分配的时候,看见了ALIGN_SIZE宏,知道是用作字节对齐的,实现原理如何不甚很明白,在网上查了一下。找到了这么一篇http://bbs.chinaunix.net/archiver/tid-846225.html解释,该页面布局不太好看,就搬到这里来了。很实用的。

原帖内容:

以前对于这个宏有讨论过,不过似乎都讲得很模糊,作为一个知识点不应该有模糊
这个宏的目的是:将地址值调整为下一个边界上。
先问问自己:我应该怎么去实现这个功能呢?
假设: addr = 0xbfdf8cf3    
   
也就是:1011
1111 1101 1111 1000 1100 1111 0011

那么:如果我要将这个值调整到下一个2字节边界上
      
就应该是:xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx10
         
也就是2的倍数上。
      
如果我要将这个值调整到下一个4字节边界上
      
就应该是:xxxx xxxx xxxx xxxx xxxx xxxx xxxx x100 
      
也就是4的倍数上。
      
最后,如果我要将这个值调整到下一个8字节界边上
      
就应该是:xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1000
         
也就是8的倍数上
怎么做呢? 我必须根据所要调整边界的要求 addr 的低几位置 0,同时还要增加一个 模值
例如:我要将 addr 调整到 4 字节界上,于是我就有一个初步的想法
1
addr 加上 0100 使它跳到下一个 4 字节
    addr + 0000 0000 0000 0000 0000 0000
0000 0100

      
结果为:1011 1111 1101 1111 1000 1100 1111 0111
2
、将上一步的结果低 2 位清 0,从而实现调整要求
   1011 1111 1101 1111 1000 1100 1111
0111
 
&  1111 1111 1111 1111 1111 1111
1111 1100

--------------------------------------------------------------
    1011 1111 1101 1111 1000 1100 1111
0100

3
1111
1111 1111 1111 1111 1111 1111 1100
怎么通过 4 运算得出来呢?
   
负数:-4 在机器中表示为: -4 = ~4 + 1
          
   
即: 1111
1111 1111 1111 1111 1111 1111 1011    
   =  ~4

          
       + 0000 0000 0000 0000 0000 0000 0000 0001 
      =  1

          
  
   -----------------------------------------------------------------------------

          
          1111 1111 1111 1111 1111 1111 1111
1100        =  -4

   
4
、总结一下,得出以下算法
    (addr + align_size) &
(-align_size)

所以:我可以这样定义这个宏
#define PAGE_ALIGN(addr,
align_size)  ((addr+align_size) & (-align_size))

而后来:我发现,只要加上被清0位数上的最大值,就可以跳到下一个对齐边界上,
        
也就是: 4 字节对齐时,只要加上3就可以了,
          
      8
字节对齐时,只要加上7就可以了,
          
      2
字节对齐时,只要加上1就可以了,

          
 
即: addr + align_size - 1 就可以了 !!!
        
下一步做 & 时:4字节对齐,只要将 3 取反就得出 0xFFFF FFF4
          
                 
      8
字节对齐,只要将 7 取反就得出 0xFFFF
FFF8

          
                 
      2
字节对齐,只要将 1 取反就得出 0xFFFF
FFF2

    
于是: 我就有了算法的另一个版本:
       ( addr + align_size - 1
) & (~(align_size - 1))      
 
最后, 我就可以将宏定义为:       
#define PAGE_ALIGN(addr, align_size)
((addr+align_size-1) & ~(align_size-1))

也就是,LZ 所问的宏是怎么来的

补充一点:

(addr + align_size) & (-align_size)

这个算法,忽略了对 低几位是 0 的情况的考虑!

如果:xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx00 
这种情况的话 addr + align_size 导致空跳到下一边界
addr + align_size - 1 无论什么情况下都是正确的。

-align_size 与 ~ (align_size - 1) 本质上是一样的, 而 - align_size 似乎更好理解,建议采用这种形式 

 

讲得很细,真是学习了,在此谢谢作者的讲解,也谢谢MySQL团队,谢谢开源,谢谢每一个乐观向上的人

【上篇】
【下篇】

抱歉!评论已关闭.