GlobalLock的前世今生2: 选择子

GlobalLock的前世今生2: 选择子

作者:BlogUpdater |  时间:2021-12-19 |  浏览:1226 |  评论已关闭 条评论

随着英特尔80286的到来,Windows就可以使用处理器的”保护模式”了。但是,当时还是没有虚拟内存技术,却带来了内存保护技术。全局句柄转变为”描述符”,它广为人知的名字是”选择子”(Selectors)。

从架构上来说,80286同时支持本地描述符表(Local Descriptor Table)和全局描述符表(Global Descriptor Table),这就可以实现单个进程运行在其独立的地址空间上,但是这会导致Windwos 1.0的兼容性问题,因为当时的内存都是全局性的。

80286的内存保护模式包含一个选择子(selector)和一个偏移(offset),而不是一个段(segment)和一个偏移(offset)。这样的改变看起来微不足道,但是它实际上十分重要,因为一个选择子的行为就像一个硬件中的句柄表那样。

当你创建一个选择子时,你会指定一系列的属性,例如它是一个代码选择子(Code Selector)还是一个数据选择子(Data Selector),它是有效的还是被丢弃的,以及它是否在内存中(如上面所述,当时没有虚拟内存,所以所有的内存都是物理内存)。

GlobalAlloc现在将会返回一个选择子,如果你想的话,可以直接把它当做内存地址的选择子来使用。当你加载一个选择子后,CPU会检查此选择子的有效性:
> 如果它是有效的,则一切都会顺利。
> 如果它是被丢弃的,则一个”选择子无效”的异常将会被激发。内存管理器会陷入这个异常,然后采取必要的措施来使之变得重新有效。这意味着,内存管理器会分配内存(可能会压缩并释放空间来实现),如果它是一个代码选择子,则还会从磁盘中重新加载代码并修复。
> 如果它是无效的,则一个”无法修复的应用程序错误”会被激发,这就是大家所所知的”UAE”。

因为内存访问会自动被转化为硬件上的描述符表操作,这意味着内存可以被来回移动。所有现存的指针会继续保持有效,因为选择子继续保持有效。所有的变化都保存在内部的描述符表中,这些表会用来指定那些描述符指向哪些内存段。

为了保持与Windows 1.0的兼容性,GlobalAlloc继续模拟之前的内存移动性规则,只是数字型的选择子不会再改变了。接下来我们会进入Win32的世界。

总结
Windows10和Windows1.0,虽然只是一个小数点的差别,但是它们之间却经历了漫长的变迁,也凝结了广大开发人员的心血。
Topomel Box目前已经经历了1.0和2.0版本,正在向3.0迈进。
在有限的生命中,我们确实需要做点什么,在茫茫宇宙长河中,留下点属于我们自己的印记。

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

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

标签:

评论已关闭。