关于x86平台上内存对齐的重要性

关于x86平台上内存对齐的重要性

作者:BlogUpdater |  时间:2021-09-24 |  浏览:133 |  评论已关闭 条评论

有时候,未对齐的内存访问,可能会导致系统挂起。

有一些显卡不允许驱动程序一次性就访问所有的显卡内存。取而代之的做法是:它给你一个访问窗口,你可以从中选择一个显存的子集来进行访问。举个例子,EGA显卡有256K的字节空间,它们被划分到4个64K的存储单元中。如果你希望访问第一个64K,则你需要将这个64K空间(bank 0)选择到访问窗口中,同样的道理,如果你需要访问第二个64K,则你需要将它(bank 1)选择到访问窗口中。

基于存储单元的访问机制,使得内存访问变得复杂起来,举个例子,如果你希望拷贝一块内存数据到一个存储单元中,你需要首先检查这个目标内存空间是否跨越了存储单元的边界,并将数据拆分成片段进行拷贝动作。
如果你正在执行的操作需要一段连续性内存访问(例如,在屏幕上绘制一条对角线),则你还需要判断这条线是否会跨越存储单元的界限。

为了简化这一操作,Windows 95引入了一个名为”VFLATD”的驱动,可以用来将单元式访问抽象化为平坦式内存访问。这一转换机制对于DirectDraw也十分重要,特别是IDirectDrawSurface::Lock方法可以提供对平坦的显卡内存进行直接访问。举个例子,如果应用程序想观测到256K的表面(surface)并访问其中第一个64K的空间,VFLATD驱动就会将第一个64K选择到访问窗口提供访问接口。

这种设计对于那些遵循了内存对齐的代码很奏效,但是如果你访问了未对齐的内存,则这会导致VFLATD驱动进入一段无限循环,并最终导致机器挂起。

假设你进行跨越两个存储单元的未对齐内存访问。这种内存访问永远无法满足。在未对齐访问的较低部分发生页面错误(Page Fault),VFLATD将较低的存储体映射到内存中。然后在未对齐访问的较高部分发生页面错误,VFLATD现在必须映射较高的存储空间,这将取消映射较低的存储单元,因为显卡是基于存储单元进行切换的,一次只能映射一个单元。现在在内存下部发生页面错误,并且会一直无限循环。

这个故事的寓意:请保持内存访问对齐,即使在x86平台上也是如此,大多数人会认为违反对齐规则是安全的。这可不大对。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Importance of alignment even on x86 machines》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

评论已关闭。