互联网的好人!
在过去的几天里,我一直在阅读有关 CPU 如何访问内存以及如果访问的对象分布在 CPU 访问的不同块上,它会如何变慢。
用一个非常笼统和抽象的话来说,如果我有一个从 0x0 到 0xF 的地址空间,其中一个字节的单元格,并且 CPU 以 4 字节的块读取内存(即,具有四字节的内存访问粒度),然后,如果我需要读取位于单元格 0x0 - 0x3 中的 4 字节大小的对象,CPU 将在一次操作中完成,而如果同一对象占用单元格 0x1 - 0x4,则 CPU 需要执行两次读取操作(读取内存首先在 0x0 - 0x3 中,然后在 0x4 - 0x7 中),移位字节并组合两个部分(或中断,如果它不能进行非对齐访问)。这再次发生,因为 CPU 可以读取 4 字节块的内存(在我们的抽象情况下)。我们还假设,CPU 在一个高速缓存行内进行这些读取,并且在读取之间不需要更改高速缓存的内容。
因此,在这种情况下,CPU 可以读取的每个块的开头都驻留在地址为 4 的倍数的内存单元中(对吗?)。好的,我对 CPU 读取块的原因没有任何疑问,但是why exactly the beginning of each chunk is aligned in such a way?如果参考上一段中的示例,why exactly CPU cannot read a chunk of 4 bytes starting from 0x1?
据我所知,CPU 非常清楚 0x1 的存在。那么所有的fuzz都是因为内存控制器无法访问从0x1开始的内存块吗?还是因为在某些架构上保留了处理器字中的几个 LSB?或者它们被保留的事实是对齐访问的结果,而不是它的原因(似乎已经是第二个问题,但我会留下它,因为在我写这个问题时我觉得它们是相关的)?
这里有很多关于这个主题的答案(比如这个和这个)和在线文章(比如这个和这个),但是在所有的资源中都有关于现象本身及其后果的很好的解释,但没有解释为什么 CPU无法读取从“介于”字节边界之间的内存块(或者我可能看不到它)。