我知道这个问题已经被问过一千次了,我已经阅读了每一个答案,但我仍然不明白。我的 RAM 模型可能存在一些根本性错误,使我无法理解任何答案。
我从互联网上得到了所有这些小信息,但我就是无法将它们联系起来。
以下是我认为到目前为止所知道的:以 IA-32 架构为例,其字边界为 32 位(边界 = CPU 可以从内存读取的最大值?)。它将始终在其字边界内读取。
1)那么,无论我给它什么地址,它总是会读取4个字节?如果我在地址 x 处有一个简单的字符怎么办?它会从该地址读取 4 个字节,然后执行一些奇怪的操作以仅获取一个字节吗?
2)如果是这样,那么一个字符串(字符序列)n_chars * 4字节大吗?我很确定事实并非如此,但是我该如何解释“将始终读取其单词边界”呢?
3)内存对齐似乎只与数据结构有关。为什么?内存的其余部分是否未对齐?我的意思是物理空间、虚拟空间、内核空间等?
4) 为什么我只能在可被4整除的地址处存储32位值?我的意思是我知道它最终只能读取 32 位,但为什么它不能从奇数地址读取 32 位呢?比如这里有什么限制?
我只是很困惑请帮助我
在现代计算机中,内存是面向字节。每个字节都有自己的地址,可以单独从 RAM 中获取。为了您的程序,您可以假设获取一个字的行为就像获取以任意顺序组成它的字节,然后将它们组装成您加载到的寄存器中的一个字。
请注意,这是一个抽象。存储芯片通常以一次读取 8 个或更多字节的方式连接。 CPU 有一些电路可以将所有这些从机器代码中抽象出来。然而,这种抽象是leaky https://en.wikipedia.org/wiki/Leaky_abstraction这会导致许多影响:
- 如果数据未符合其对齐要求,则内存访问可能会花费额外的周期,因为数据跨越的字数超出了所需的字数。通过充分对齐数据可以避免这种损失。
- 当获取或写入对齐数据时,这会转化为硬件中的单个获取或存储。这样的获取或存储是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 和操作系统:
- 它只是有效
- 它可以工作,但速度有点慢
- CPU默默地忽略低2位并从相应的对齐地址读取(现在这种情况很少见)
- CPU 会抛出异常,如果不处理它就会导致程序崩溃
- CPU 会抛出异常,操作系统会捕获该异常来模拟内存访问。
您通常不应该假设会发生以下哪一种情况。切勿编写读取未对齐数据的代码。如果您需要读取未对齐的数据,请考虑单独读取每个字节,然后手动将字节重新组装成您想要的数据。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)