您的位置:首页 > 其它

有关字节对齐的深入思考

2017-12-26 19:54 183 查看
前几天看到一篇博客,为什么鸟哥说 int 再怎么随机也申请不到奇数地址

字节对齐基本是个常识,但是背后的原因值得好好思考。这篇博客里提到了:

需要字节对齐的根本原因在于CPU访问数据的效率问题。因为CPU每次都是从以4字节(32位CPU)或是8字节(64位CPU)的整数倍的内存地址中读进数据的。(更深入的原因,谁告知下),如果不对齐的话,很有可能一个4字节int需要分两次读取。

那么,我就接着在我这篇博客里,聊聊为什么CPU每次都是以4字节或者8字节的方式读取数据的,有不对的地方,还请指出。

内存结构

内存的准确称呼应该叫做DRAM,动态随机存储器,它依靠其内部电容的电荷来记录信息,具有容量大、速度快的特点。内存的基本单元,是内存条上的一个个黑色颗粒。颗粒本身的数据输出都是8bit或者16bit,远远达不到现代电脑的吞吐量要求。

内存的带宽等于
时钟频率x数据总线宽度
,提高任一个都可以提高内存的带宽。前者的提升可以带来带宽的增大,但负面效果也很明显,一是功耗会急剧增大,二是硬件设计难度会增大很多,对时序的要求会更加严格。而提高数据总线宽度相对来说就好很多,可以通过叠加颗粒的方式实现。比如要实现一个32bit的输出,只需要用两颗16bit的颗粒,一颗提供D[0:15],一颗提供D[16:31]。当然,实际操作起来肯定不是把俩颗粒拼起来这么简单,还要考虑到更多复杂的因素,这里略过不谈。

因此呢,现在市面上能买到的内存条,其数据总线的输出几乎都是多颗粒拼出来的,如普通台式机内存条的DIMM标准,其数据总线宽度为64位,要用8颗8bit颗粒或者4颗16bit颗粒来拼。不过,不用考虑这么多的细节,把它当作一个大号64bit位宽颗粒就可以。

有了内存条以后,大带宽的存储器实现了,直接挂在CPU上?这样是不行的。内存颗粒有个重要的特性叫做易失性,它需要定时进行刷新操作来维持内部电容上的电压。实现这部分逻辑的东西叫做内存控制器。

CPU数据总线宽度的变迁

数据总线宽度代表了CPU一次能读取的数据大小。

就从我知道的比较早的CPU开始说吧,8080,intel的产品,数据总线宽度为8位,也就是说,CPU一个时钟周期可以加载1字节的数据。后来,CPU处理能力越來越强,数据总线宽度逐渐扩大,8086的16位,到32位,64位等。然而软件代码里的地址的单位却一直都是字节,这也为后面字节对齐埋下伏笔。

数据宽度的差异

前面提到了,软件代码里至今地址的单位一直都是字节,但在底层硬件,早已不是这样了。假设一个32bit位宽的存储器,当地址总线上出现的是0x0000时,数据总线上出现的是0~31bit的内容。当地址总线上出现的是0x0001时,数据总线上的内容已经变成了32~63bit的内容。可以看到,硬件为了最大限度的利用数据总线,并不是按照字节来存储的,而是按照实际位宽去存储的。节约地址总线的宽度,就意味着更少的引脚、更低的功耗。

比如一个4Gb(注意是比特不是字节)的内存,其总的存储容量为2^32bit。

如果按照代码中8bit一个地址的话,那么地址总线的宽度为32-3=29bit,总的存储容量就是2^29 * 8bit = 1024 * 1024 * 512 Byte = 512MByte.

如果按照内存输出32bit来计算的话,内存接口提供的地址总线宽度只有32-5=27bit,总的存储容量守恒,仍然是512MByte,只是计算方法变成了2^27 * 32bit = 1024 * 1024 * 128 * 4Byte = 512MByte.

举个例子

假设有一段内存dump如下, 四个char类型:abcd和一个int类型的0x12345678。假设内存的位宽是32bit。

0x0000  'a'
0x0001  'b'
0x0002  'c'
0x0003  'd'
0x0004  0x78
0x0005  0x56
0x0006  0x34
0x0007  0x12
...


那么在实际访问时,比如访问0x0001位置,这个地址经过内存控制器转换后,实际传递给内存的地址是0x0000,出现在数据总线上的数据是0x61626364。内存只可能一次性送出其数据总线宽度的数据,大于或者小于都是不行的。说白了,代码的层面只访问1个字节,内存则一次性给出4字节的内容,要哪个字节,交给上面去判断

进一步推断,如果代码里发生了四次读取操作,分别是0x0000, 0x0001, 0x0002, 0x0003,那么,内存的数据总线和地址总线都不会发生任何变化。直到读取0x0004位置时,内存的地址总线才会切换到0x0001,并送出0x12345678。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: