为什么需要内存对齐?

时间:2017-10-28 15:35:09

标签: assembly memory x86 alignment low-level

我知道这个问题已被问过一千次了,我已经阅读了每一个答案,但我仍然没有得到它。可能在我的RAM模型中存在一些基本错误,这使我无法理解任何答案。

我从互联网上获取所有这些小信息,但我无法连接它们。

到目前为止,我想知道的是:例如,以IA-32架构为例,字边界为32位(边界= CPU可以从内存中读取的最大值?)。它总是会读到它的单词边界。

1)所以,无论我给它什么地址,它总是会读4个字节?如果我在地址x处有一个简单的字符怎么办?它会从该地址读取4个字节然后做一些奇怪的事情来获得一个字节吗?

2)如果是这样,那么是一个字符串(一系列字符串)n_chars * 4字节大吗?我很确定它不是那样的,但是我怎么解释“总会读出它的单词边界”呢?

3)内存对齐似乎只提出数据结构。为什么?内存中的内存是否未对齐?我的意思是物理,虚拟,内核空间等?

4)为什么我只能在可分为4的地址存储32位值?我的意思是我得到它最终只能读取32位,但为什么它不能从奇数地址读取32位?喜欢这里的限制是什么?

我很困惑请帮帮我

1 个答案:

答案 0 :(得分:2)

在现代计算机中,内存是面向字节的。每个字节都有自己的地址,可以单独从RAM中获取。为了您的程序,您可以假设获取一个单词的行为类似于获取以任意顺序组成的字节,然后将它们组合到您加载到的寄存器中的单词。

请注意,这是一个抽象。存储器芯片通常以一次取出8个或更多字节的方式接线。 CPU有一些电路可以将所有这些从机器代码中抽象出来。但是,这种抽象是leaky,会产生许多影响:

  • 如果数据未与其对齐要求对齐,则内存访问可能需要额外的周期,因为该数据跨越了超过必要的字数。通过充分调整数据可以避免这种惩罚。
  • 在获取或写入对齐的数据时,这会转换为硬件中的单个提取或存储。这样的获取或存储是 atomic ,它是并发代码中的重要属性。在获取或写入未对齐的数据时,需要多个提取或存储,操作不再是原子操作。
  • 有些CPU根本不支持读/写未对齐的内存,因为这简化了电路设计。这种限制在当代硬件中越来越少见。

现在,问你的问题:

  

1)所以,无论我给它什么地址,它总是会读4个字节?如果我在地址x处有一个简单的字符怎么办?它会从该地址读取4个字节,然后做一些奇怪的事情来获得一个字节吗?

也许。这取决于您使用的硬件。但是,如果您请求一个字节,您将只获得一个字节。您不应该关心硬件读取多少字节来为您提供一个字节。

  

2)如果是这样,那么是一个字符串(一系列字符串)n_chars * 4字节大吗?我很确定它不是那样的,但是我怎么解释“总会读出它的单词边界”呢?

字符串通常n_chars字节大。当您从字符串中读取一个字符时,您将获得一个字节。硬件可能会读取更多字节来满足您的请求,但这不是您需要关注的事情。请注意,Windows有时会使用UTF-16字符串,每个字符占用两个字节,但这种趋势并没有真正流行起来。

  

3)内存对齐似乎只提出数据结构。为什么?内存中的内存是否未对齐?我的意思是物理,虚拟,内核空间等?

只要您考虑RAM中的数据,内存对齐就很重要。在内核或用户进程内部使用该内存并不重要。 MMU通常以保持对齐的方式映射内存,因此如果使用物理或虚拟内存则无关紧要。磁盘上的数据没有这些对齐要求,但由于您使用的存储的扇区大小,可能会应用其他性能特征。

  

4)为什么我只能在可分为4的地址存储32位值?我的意思是我得到它最终只能读取32位,但为什么它不能从奇数地址读取32位?喜欢这里的限制是什么?

如果从奇数地址读取32位,则会发生以下情况之一,具体取决于您的CPU和操作系统:

  1. 它正常工作
  2. 它有效,但有点慢
  3. CPU默默地忽略低2位并从相应的对齐地址读取(现在很少见)
  4. 如果您不处理程序,CPU会抛出异常会导致程序崩溃
  5. CPU抛出一个异常,操作系统捕获该异常以模拟您的内存访问。
  6. 您通常不应该假设这些发生了哪些。永远不要编写读取未对齐数据的代码。如果需要读取未对齐的数据,请考虑单独读取每个字节,然后手动将字节重新组合到所需的数据中。