苦涩後的甘甜-Windows 系统深耕

>>>  名人論史——近當代作家的史學觀點  >>> 簡體     傳統

1997.03

探索作业系统,当然苦涩。
练习 system programming,当然痛苦。
但是历炼过後,那种掌握来龙去脉、洞悉系统奥秘的感觉,
又让我们苦後回甘,如溽夏苦茶。


关於 Windows 作业系统,首先我要说点和我个人有关的题外话。

话说我那在淡江大学就读资讯系三年级的表妹,去年修了一门「作业系统」课程。期中考采分组报告形式,由各组挑选主题做专题报告(口头加书面)。我这表妹非常英勇威武地挑了「虚拟机器」这个题目(真是初生之犊不畏虎呀),然後听说表姊夫好像在这个领域有点心得,还发表过相关文章,於是邀我喝杯咖啡,顺便问候一下表姊的生活,顺便...呃...聊聊 Windows 虚拟机器。而我也以演讲所用的三两投影片略尽棉薄。

後来,她很高兴地打电话来告诉我,老师相当满意她这一组的表现,并且在得知我就是我的表妹的表姊夫之後,邀请我到学校做个演讲。我因此认识了好几位系上老师和近百位系上同学。你看,人生多麽奇妙!倪匡有一本小说讲人的前世今生,他说你这一辈子所接触的人都在前世彼此有所纠葛关联。啊,缘份很是奇妙!

故事还没有结束。上个月我叁加一个尾牙聚餐,近尾声时厕所人满为患。我正排队等候,冷不妨一声

『请问您是侯老师吗?』旁边队伍的邻兵说。
『喔,是的,请问您是...』
『我是您的读者啦,上次您到淡江演讲,我也在场听讲』
『喔,是是...』。

轮到我们双双就战斗位置,一阵寂静之後...

『侯老师,我正在读您的那本 Dissecting MFC』,
『喔,是是...』,
『里头第三章我觉得真好』,
『喔,是是,谢谢...』,
『我可以 mail 给您讨论问题吗?』
『喔,是是,当然当然...』。

有点儿尴尬,在那样的场合。不是有人说过吗,千万别在厕所里认人。切记!切记!

言归正传。这次我的主题正是 Windows 作业系统。对於电脑的终端使用者而言,作业系统提供的应该是一层不见晦涩的服务。一层虽然让你感觉不出,却能够使每件事情每个动作顺畅无碍的环境。

作业系统之於终端使用者,差不多像那种「紧贴着你的肌肤,但是薄得感受不到」的东西。作业系统之於软体开发者,则出现一种论调:『谁管什麽作业系统,我的程式写得好就好了』。也对,问题是,怎麽样能够把程式写得好写得完全?这和软体开发的目标与定位有关系。如果你的目标在除错软体(我是指像CodeView、SoftIce/W、BoundsChecker、Winspect 等产品),或是工具软体(我是指像 DUMPBIN、HeapWalk、WinSpy 等产品),你当然不能不对作业系统有深刻的了解。即连一般的 Windows 应用程式设计,也多少需要某种程度的作业系统知识,程度的多寡深浅则视使用哪一种开发工具而定。如果你用的是 Visual Basic、MFC 或OWL、Delphi、RAD 开发环境(如 C++ Builder),你不需要太多的作业系统知识。如果采用SDK programming,则对作业系统需要相当深度的涉猎,否则一知半解,恐怕临渊履薄,状况频出。

话说回来,使用 SDK 的所谓「古典派 Windows 程式设计者」,可以因为使用并了解系统提供的 APIs,而对系统的行径有所掌握,对整个庞大机制的运作有所概念。这些人在技术层次上就不是光光 application framework 或 RAD(Rapid Application Development)的使用者能够望其项背的了。我在学校开授 Windows 作业系统课程,就要求同学必须先有SDK programming 的基础。没有这种基础而想修行 Windows 系统,有点自讨苦吃。

探索作业系统,当然苦涩。练习 system programming,当然痛苦。但是历炼过後,那种掌握来龙去脉、洞悉系统奥秘的感觉,又让我们苦後回甘,如溽夏苦茶。

今天介绍的三本 Windows 作业系统书籍,大抵也就是你所能找到的仅有的三本相关店头书籍(trade book)了。比较带点学术味道的相关教科书(text book)也有,但是我对那种枯燥东西没兴趣。这些所谓的 trade books 比较活泼生动、内容也比较反应实际,和工业界的脉动比较接近。

这三本书的作者都赫赫有名,文笔洗练,Matt Pietrek 尤其带个人感情(意思就是很好看)。三位作者之大名於我都有「一定要买」的吸引力,他们都是期刊杂志上的常客,出没於 Microsoft Systems Journal 或Dr. Dobb's Journal 或 PC Magazine,也都是(或曾经是)专栏主持人。三本书都不算新,Matt 和 Jeffrey 行有年矣,Walter 亦已面世半载。

让我先对这三本书做个简介:

Windows 95 System Programming SECRETS

挖宝高手 Matt Pietrek 继 Windows Internals 後再次出马。上次对象是 Windows 3.x,这次直指 Windows 95。本书侧重在16-/32- 位元核心资料结构的介绍,及其相关函式(含未公开函式)的内部动作。这些核心资料结构包括 modules、processes、threads、tasks。本书也对 KRNL386/KERNEL32、GDI/GDI32、USER/USER32 三大模组做了非常彻底的挖掘,几乎到了寸草不留的地步。此外,隐藏在三大模组背後的 VMM、VWIN32、ADVAPI32 等神秘的 VxDs,作者也有非常深入的介绍。本书有一章专论 PE 档案格式,有一章谈探索 Windows 系统的个人经验与心得,最後一章则给你一个spy 软体设计的实务经验。本书所附程式几乎都是为证明「作者所言(的那些内部结构)不假」而设计的。

Advanced Windows(2nd Edition)

本书着重在 32 位元架构,以及与系统核心有关系的 API 函式,旨在从 Win32 API 的层面看系统。作者并不强调要「挖」出什麽内部秘密给你,而是以公开的 APIs示范诸如行程操作、执行绪操作、排程、虚拟记忆体、同步化控制等与系统有关的题目。

System Programming for Windows 95

本书着重在作业系统与硬体之间的介面、驱动程式与 VxDs,旨在从硬体与轫体(firmware)层面看系统。这是三本书中最低阶的一本,和前两本书有明显的诉求差异。

 

●Windows 95 System Progrmming SECRETS

作者:Matt Pietrek
出版公司:IDG Press
出版日期:1995 年第四季
页数:10 章,780 页
售价:US$ 49.99。含磁片一片。

1. Putting Windows 95 in Perspective
2. What's New in Windows 95
3. Modules, Processes, and Threads
4. USER and GDI Subsystems
5. Memory Management
6. VWINKERNEL32386
7. Win16 Modules and Tasks
8. The Portable Executable and COFF OBJ Formats
9. Spelunking on Your Own
10. Writing a Win32 API spy
Appendix A: The Undocumented KERNEL32.DLL Import Library

win95-secrets.jpg (18943 bytes)


让我先谈谈作者。Matt Pietrek 写过 Windows Internals (中译本名为「Windows 系统彻底研究」,旗标出版,非常棒的一本译作),那是对 Windows 3.x 的剖析,剖析方式是以大量的虚拟码(pseudo code)解释 API 函式的内部动作。我觉得这种作法棒透了,因为 API(Application Programming Interface)就是作业系统的外显特徵,提供种种供应用程式役使的「命令」。你看,如果我们知道GetMessage 如何从讯息伫列中取讯息、如何等待讯息、等待时如何配合排程器,或如果我们知道 DispatchMessage 如何取出「讯息所归属之视窗」之视窗类别中所登记的视窗函式、并模拟 MakeProcInstancec 所建立之 instance thunk,我们对系统的了解,就绝不仅仅是手册上的「抓取讯息、派送讯息」三言两语能成就。这一切奥秘,API 函式的虚拟码都可以展现出来。

现在,Matt 重施故技,矛头对准 Windows 95。为什麽不是Windows NT?唯一的理由是市场因素:在 Win32 平台中Windows 95 是众人焦点。Windows NT 曲高和寡,还没轮到它擅场。Win32s?呵,好久没听说了。

API 虚拟码不是可以瞎掰出来的,为什麽 Matt Pietrek 有这样的功力?Microsoft Systems Journal 主编 Eric Maffei 为本书所写的序可窥一二:『Matt 的技术大师生涯始自 1988 年的 Santa Cruz 大学毕业典礼。他获得的是物理学位,只修过两门电脑课程。在加入 Borland 技术支援部门之後,他很快因为一次评量而看清楚自己 -- 他获得的是最低分。转到Borland R&D 部门的那段时光比较快乐。在那里 Matt 写了TDUMP 和 WinSpector。他甚至加入 OS/2 Turbo Debugger 的开发。他的辛勤工作获得了丰富的报酬:在一次裁员行动中他失业了。最後,Matt 在 Nu-Mega 公司找到了自我。今天他是 BoundsChecker 系列产品的主要建构者。』

Nu-Mega 公司的 SoftIce/W 和 BoundsChecker 都是极佳的Windows 系统层面除错器。

这本书的排版以及校稿错误时有出现。偶有「断行」断得不适当的情形,错别字则让人怀疑是不是没有使用自动拼字检查功能?下面是一些例子:

☆ 把 abbreviated 说成 abreviated(p405)
☆ 把 16h 写成 16(p524)
☆ 把 IMakeProcInstance 写成 MakeProcInstance(p540)
☆ 把 .drectve 写成 .drective(p585)
☆ 把 directly 写成 directlyl(p586)
☆ 把 RtlAllocateHeap 写成 RTLAllocateHeap(p87)
☆ 把应该说 section 的地方说成 segment
☆ 把 002A0040 写成 0002A0040 (p322)
☆ 把 VirtualFree 说成 VirtualAlloc (p319)
☆ 把 HeapWalk 说成 HeapAlloc (p379)
☆ 把 SetWindowLong 说成 SetWindowWord (p639)
☆ 把 from left to right 说成 from right to left (p650)
☆ 把 will be changed to 1 说成 will be incremented (p661)
☆ 把 Get_VMM_Version 说成 Get_Cur_VM_Handle (p679)
☆ 把 IMPLIB.EXE 说成 IMPORT.LIB (p759)


这样的错误估计约有 25 个之多。会不会造成误解,那就要看你的底子了。显而易见这是赶工的结果。赶什麽?赶当初Windows 95 的上市。所以我说嘛,慢工出细活,快手无好货。我认为 IDG Books 出版社对待大师级作品实在太过轻佻,Windows Internals 在 Addison Wesley 发行,就不曾出现这种现象。IDG Books 出版社向以市场导向闻名,有一套 for dummies 系列,听说还有一套 for idiot 系列。我老天!

Matt 的文笔很活泼也颇直率,他对微软的批判态度往往露骨地显现在字里行间,读起来辛辣过瘾。这种文字放在杂志期刊上颇合适,放在书籍上则过犹不及。此外,你可以称Matt 为罗唆先生,叙述起事情来虽然条理分明,但用词累赘。还好这不会影响读者的权益 -- 同样的东西多说两次没有什麽害处。

现在我们来看看这本书的牛肉在哪里。本书第一章概述三个Win32 平台:Win32s、Windows NT、Windows 95。第二章一开始就进入高潮,把 Windows 95 的遮面纱掀开来,曝露出其中的 DOS 血统。这一章告诉你 Windows 95 中 32 位元和16 位元成员的合作关系,以及强制性多工和合作型多工之间的妥协(关键在於 Win16Mutex)。

第三、四、五章分别就其主题深度挖掘其间的系统资料结构,以及对应之 API 函式或内部函式的虚拟码。第六章章名奇特,Matt 语不惊人死不休,VWINKERNEL32386 = VWIN32.VxD + KERNEL32.DLL + KRNL386.EXE。对作业系统基本教义派人士而言,USER 和 GDI 子系统可能都不值一哂,唯以上三元素是 KERNEL 子系统的中坚份子,一个是 ring0 VxD,一个是32 位元 DLL,一个是 16 位元 DLL,三者互通款曲。这倒也是 Windows 95 的独特生态。

第七章介绍 Win16 modules 和 tasks。作者开宗明义这麽说:『在一本专注於 Windows 95 32 位元架构的书籍中放一章 16 位元 KERNEL 资料结构,是不是有些诡异?然而,很快你就会看到,这些资料结构在 Windows 95 之中扮演非常重要的角色-- 对 16- 或 32- 位元程式都是如此。』这一章对 KRNL386 所维护的 16 位元 modules 和 tasks 做了一次导游。

第八章介绍 PE 可执行档格式。这个题目对於 Win32 程式载入、DLL 模组载入、函式输入与输出(import/export)、动态联结机制等等有着密不可分的关联。Matt 的分析非常透彻,磁片中的 PEDUMP(附原始码)则是其实作产品,可分解 PE 档案,将其中一个个的 sections 的内容有意义地呈现出来。

第九章是 Matt 的私房菜,是他使用各种分析工具的经验,以及反组译的实务心得。第十章(最後一章)的 spy 软体设计,则是对整个系统结构工程的总验收。Matt 让我们见识什麽叫做山川壮丽,什麽叫做鬼斧神工!要完成一个非常有弹性,而且面面俱到的spy 软体,你需要许多作业系统的知识,以及编译器的知识。你必须熟悉 PE可执行档格式(尤其在 PE header 以及 import section 方面),你必须熟悉函式呼叫时的叁数传递方式以及回返位址的设定(也就是堆叠的状态),你必须知道中断点与除错讯息,以及除错器与被除错程式的关系,你必须知道有哪些 API 可以跨越行程处理别人的位址空间中的内容,有哪些方法可以突破行程间的位址空间藩篱,你也必须知道thread context 中的 EIP(Extended Instruction Pointer)作用。我非常欣赏这第十章。

本书深度够、密度高。以资讯份量而言,真正是物超所值!如果硬要说不足,我想是对於知识的表达方式吧。Matt 颇能够实践「惜图如金」的精神,许多观念或资料,配合一张图可以表现得淋漓尽致,Matt 却不。整本书虽然有些不错的示意图,但和浩瀚字海比起来,如沧海一粟。

钻研 Windows 95 系统,是不是一项划算的投资?不是还有Windows NT 吗?95 和 NT 不是有许多不同吗?呵呵,学问是堆积起来的。基础愈深,堆得愈高;基础愈广,堆得愈快。触类旁通是我们在这个千变万化一日千里的领域中最大的依侍。这本书让我们全盘了解 Windows 95,而 NT 只在隔壁房间。

 

●Advanced Windows(2nd Edition)

作者:Jeffrey Richter
出版公司:Microsoft Press
出版日期:1995 年第三季
页数:16 章,930 页
售价:US$ 44.95。含光碟一片。

1. The Win32 API and Platforms That Support It
2. Processes
3. Threads
4. Win32 Memory Architecture
5. Exploring Virtual Memory
6. Using Virtual Memory in Your Own Applications
7. Memory-Mapped Files
8. Heaps
9. Thread Synchronization
10. Window Messages and Asynchronous input
11. Dynamic-Link Libraries
12. Threead-Local Storage
13. File Systems and File I/O
14. Structured Exception Handling
15. Unicode
16. Breaking Through Process Boundary Walls
Appendix A: Message Crackers
Appendix B: The Build Environment

advanced-win-v2.jpg (15684 bytes)


同样地,让我先谈谈作者。前面说过 Matt 擅长挖掘系统内部资料,本书作者 Jeffrey则靠着 Windows 程式设计和系统知识两方面的专业而知名。在程式设计方面,他写过经典好书Windows 3.0:A Developer's Guide(後来又有 3.1 和 95 两版)。在系统知识方面,他写过 Advanced Windows NT,也就是Advanced Windows 的前身。这前後两版书籍的封面都很酷,乌七麻黑的油画里头有三两个中古法国军官,颇有传承味道。Jeffrey 的随书磁片范例程式都包装得十分华丽,Advanced Windows 的安装程式会现出一个有着书籍封面做为主要图像的对话盒。

:Jeffrey 的另一本书 Windows 95:A Developer's Guide,其安装程式更有 autoplay 功能,以及一段 video/audio,还有工作人员的名单(类似电影散场前的字幕效果),真真绚丽夺目,噱头十足。奇怪的是,这麽好的一本书(Windows 95:A Developer's Guide),为什麽国内出版社没有人争取中文化译权?难道对於这一类高档书籍,大家目光都只放在技术大厂如 Microsoft Press 或 Addison Wesley 身上?遗憾之至。

回头来看 Advanced Windows 的内容。同样是谈系统知识,这本书和 Matt 那一本最明显的区隔是它不谈内部(未公开)的结构与函式,它讲台面上的东西。好比说第二章 Processes,Jeffrey 非常详细地解释每一个和 process 有关的 APIs,解释其功能、叁数、传回值。第三章的 Threads 和第四章的Win32 Memory Architecture,以及後续所有的章节,也是以同样的方式进行。适当时候 Jeffrey 会给一个范例程式,利用他独特的创意,根据一个有趣的构思,把介绍过的 APIs 演练一遍。本书所有的范例程式都是 dialog-based,换句话说,WinMain() 之中只单纯呼叫 DialogBox(),其馀所有动作在 DlgProc() 中完成。虽然这种方式可以遂行作者所希望的「把程式所示范的动作集中在正讨论的主题上」,而导至比较容易的阅读,比较少的篇幅,不过由於 Jeffrey 大量使用 WINDOWSX.H 的讯息剖析器(一大堆巨集),使得这些程式的形式乍见之下有点儿古怪,恐怕你需要一点点适应时间。

和 Matt 的第 10 章一样,Jeffrey 的第 16 章也有一个集技术大成的范例 InjLib,而且是个可重复使用的函式。这个函式需要行程、执行绪、位址空间、同步化控制、动态联结函式库、结构化异常处理、Unicode 等技术。事实上 Matt 第 10 章的 Spy 程式亟需「把某个 DLL 注射到另一行程的位址空间中」,正是 InjLib 的功能。Matt 亦在他的书中提到了 Jeffrey 的作法,只不过他另创新法,弭补了一些缺憾。Jeffrey 说『如果你了解 InjLib,你就有资格说自己懂所谓的 Win32 程式设计了』。观察其间技术,我想 Jeffrey 的门槛实在不低。

这本书的书名之所以把前一版的 "NT" 字眼去除,因为它同时涵盖了95 和 NT。凡未特殊声明者,便是普遍的、一般的 Win32 观念与技术,而在特别针对 95 或 NT 之处,作者以明显的图示提醒读者。相当详实而细心。

说到这本书,我忍不住要提一下其中译本(张永庆/松岗)。电脑书中译本胆敢有译序,口气不卑不亢又言之有物,就已经够吸引人并让我暗暗叫好了。仔细观之,此书算得上国内高档技术书籍中难得的作品。虽说翻译水准并不是一直维持在高档次,但总的来说令人满意,可看出是出自内行人之手。书中偶有一些错别字倒是无伤大雅,把SetThreadPriority 的「不可累加性」译为「可累加性」(译本 59 页),是比较严重的错误。有时候,打个盹儿眼睛一花,把正面译为负面,校稿又没校出来,就出现这种对不起读者的错误。这种错误我要很难为情地说:我也犯过。虽不是情有可原,倒也其景可臆,其情可悯。但是把一个叁数名称 lpszMutexName 译为「lpsz多工器Name」(译本285页),就很离谱并且让人难以想像是什麽原因了。愈到後面,感觉愈往下走。到了第16章技术的顶峰,却是翻译品质的谷底,至此我不太有把握译者的水平。好比说,把 send or post 译为「投递、寄到」(译本 786 页),并不能够让读者知道原意,因为 send 和 post 是两个独特而不同的讯息传递动作,即使翻译,也应该注明原文。整章文字有一种扑朔迷离的朦胧感,不够精准。但是在某些地方,又看得出译者是懂得些门道的。

这本书挂名主译的是张永庆先生,目录之後列出所有译者(共五位)及其学识背景。我喜欢这种明明白白的作法,如果能够列出哪一章由谁翻译,厘清责任归属,就更好了。千万不能明明是大杂烩,却避讳莫深,更不能蒙上眼睛就以为看不到, 着耳朵就以为听不到。我知道有些书籍被大卸八块,译好之後又没人肯挂名(谁敢?),只好抓瞎抓个倒楣鬼来挂。诸君可以想像那种书籍的品质。电脑技术汰旧换新这麽快速,以团队方式来翻译书籍是可以被接受的,但团队要有团队的样子,团队的品质。
虽然举出前面几个缺点,但别忘记我说过这译本『算得上是国内高档技术书籍中难得的作品,出自内行人之手』。看多了「志村大爆笑」级的各种译本後,我对这几位译者的崛起,欣喜异常,期望多多。

新书通报:本书已有第三版,名称没变,封面则回归「主流」-- 不再是乌七麻黑的中古法国军官,回归到和 Programming Windows 95、Programming Windows 95 with MFC 一样的制式风格。这有点令我失望,想像中第一流作家总是「该」桀骜不驯些。我还没有看过内容,从目录观之,第一章增加了 Windows NT 4.0 和 Windows CE 的简介,另增加了Kernel Objects 和 Device I/O 两章,以及一个新的附录,介绍 Fibers(Windows NT 4.0 所提供,比 thread 更细微的东西)。


Advanced Windows 3/e

advanced-win-v3.jpg (15457 bytes)

 

●System Programming for Windows 95

作者:Walter Oney
出版公司:Microsoft Press
出版日期:1996 年末
页数:17 章,715 页
售价:US$ 39.95。含光碟一片。

Part I. Intruduction
1. Overview
2. Flavors of Windows and Drivers
3. Windows 95 System Architecture
4. Interfaces for Systems Programming
5. System Programming in Assembly Language
Part II. Virtual Device Driver Basics
6. The Virtual Machine Manager
7. Virtual Device Driver Mechanics
8. Initializing and Terminating Virtual Device Drivers
9. Basic VxD Programming Techniques
10. Helping Windows 95 Manage Virtual Machines
Part III. Input/Output Programming
11. Introduction to Plug and Play
12. Configuring Devices
13. Input/Output Programming
14. Communications Drivers
15. Block Device Drivers
Part IV. Extending the Operating System
16. Installable File Systems
17. The DOS Protected Mode Interface
Appendix A: Plug and Play Device Identifiers

win95-systemprogramming.jpg (17461 bytes)


我还是要先谈作者。Walter Oney 不比 Matt 或 Jeffrey 那麽有广泛的知名度,但他在期刊上偶而发表一些偏系统低阶的文章,也是实力派作家。自从我知道他有这个写作计划,就盼呀盼的,盼了一年有馀,他老人家终於出书了。

你很容易就可以从目录中比对出此书与 Matt 和 Jeffrey 的差别:自从 Part2 之後,就几乎全与硬体(或虚拟硬体)打交道了,这些部份占总篇幅的 88%。即使在Part1,也是三两下离不开 VxD、ring0、DMA、CR0、CR3、callgate...。在程式实作方面,Matt 和 Jeffrey 都写 ring3 应用程式,Walter 写的则是 ring0 VxD。你会获得一种完全不同的视界开展(与迷惑)。VxD 的程式架构完全不同於一般Windows 程式,虽然对等於 window procedure 它也有所谓的Device Control Procedure,对等於 window message 它也有所谓的System Control Message,对等於 Win32 API 它也有所谓的 VxD Service API,不过你很有一些新东西要面对。尤其 VxD 的开发只能仰赖 assembly 语言或C/C++ 语言,除了 Vireo Software 公司的 VToolsD 之外又没有第二套整合开发环境,益发增加它的神秘性和困难度。日昨我才和我的工研院朋友通过电话,他说新计划里头要写 VxD。『要命,谁知道VxD 怎麽写啊!』他带着夸张的口气说。我可以想像成天在高阶如 MFC 中打滚,用惯各种Wizards 的人,面对 VxD 的表情与心情。

Part1 的各章都是概念性介绍。Part2 一开始(第六章)介绍VMM,范围集中在记忆体管理、中断处理、执行绪排程三个功能。第七章可做为你踏进VxD 程式设计的第一个台阶。Walter 以 44 页的篇幅介绍 VxD 档案格式(轻描淡写)、九种 segments 以及产生它们所需使用的巨集、VxD 连结方式、DEF 档案写法、VxD 开发流程、VxD 组合语言形式、procedure 宣告方式、VxD C 语言形式。由於 VxD 形式十分标准,程式码产生器就有了一个生存空间。VToolsD 的 QuickVxD 工具让你以填写表格的方式,完成一个 VxD 骨干,有点类似 Visual C++ 的 AppWizard。第七章最後简介了 VToolsD 的使用方法与画面。

第八章介绍 VxD(包括静态与动态)的启动与结束。所谓静态 VxD 是指必须在 Windows 3.1 的 SYSTEM.INI 或Windows 95 的 Registry 中注册,才能够被系统在开机启动时一并载入的 VxD。至於动态 VxD,就像DLL 一样,可以让程式动态地搜寻,动态地载入。动态 VxD 是 Windows 95 的新特质,主要用以支援动态的硬体重新组态(也就是喧腾一时的 plug and play)。具体而言,这一章介绍的就是 VxD 生命起始和结束时,系统在不同时机送来的不同控制讯息、彼时的系统状态、以及彼时可安全呼叫的其他 VxD Services。

第九章就要比「骨干程式」更深入一点地研究 VxD 了。要写一个有点气候的 VxD,少不得需要呼叫其他现成的(系统的)VxD Services。即连我自己写过一个「抓取 CR3 系统暂存器」的阳春型 VxD,虽然关键只在 mov eax, cr3 这一行,抓到後也需呼叫 VMM 提供的 _MapPhysToLinear service,才有大用处。要呼叫VxD Services,你必须使用 VMMCall 或 VxDCall 巨集。这两个巨集就像「芝麻开门」,带你进入由 VMM、VWIN32、VKD、VDD...提供的巨量 services 所构成的巨大宝库中。你几乎可以为所欲为。这让我联想到 Matt 在其第六章谈到VxD 时的一个观点:『由於 VxDs 可以为所欲为,畅所欲行,只要你在写应用程式时踢到铁板,你就可以写一个 VxD 并从ring3 呼叫它。某些人(包括我)主张这样的策略应该谨慎使用。我个人认为如果你能够避免写 VxD,就应该尽量避免。系统之中无限权力的东西到底还是愈少愈好。我非常忧虑有一天我的硬碟之中充斥着一大堆的 VxDs,只因为没有经验的程式员以为 VxD 是唯一解决问题的途径。』

你是不是同意 Matt 的看法,我不知道,不过我想你对 VxD 的兴趣已经被大大撩起。

如果要把功能强大无所不涵的 VxD Service 开放给 ring3 程式叫用,你就必须写一个自己的 VxD 做为中介站,把对每一个service 的 VxDCall 动作包装为一个可供 C 语言呼叫的外包函式。1000 个 Services 需要 1000 个外包函式?这是不实际的,这又让我想起怪才 Andrew Schulman,他曾在 Microsoft Systems Journal 的 1992.02 那期发表过一个Generic VxD,以单一的 C 语言介面代理所有的 VxD service,令人拍案叫绝。「DOS/Windows 虚拟机器作业环境」(侯俊杰/旗标/1993)第八章曾经详细地介绍过 Schulman 的这个作法并示范了一些应用。这本书恐怕是绝了吧我想。

除了呼叫 Services 之外,你的 VxD 可能也希望提供 Service 给别人呼叫,第九章有介绍相关作法。本章的另一个重点是介绍三个极重要的资料结构:VMCB(VM Control Block)、CRS(Client Register Structure)、TCB(Thread Control Block)。认识这三个结构,那就不只是对VxD 的撰写有帮助,而且进入「虚拟机器」的研究层面了。

第十章前半部跳离 VxD 程式设计,相当深刻地介绍虚拟机器,包括它的诞生、它的 V86 部份、它的软体中断机制。後半部则介绍如何让一个 ring3 程式直接呼叫 VxD(这也是当初使我密切注意本书的重要因素):Win16 程式必须使用软体中断2Fh/1684h,Win32 程式则直接利用三个 SDK API 函式,CreateFile、DeviceIoControl 和 CloseHandle。让一个 VxD 呼叫 ring3 程式可能吗?可能,本章後半部提到了在 Win16 和 Win32 两种环境下不同的作法。

第11章介绍 Plug & Play 驱动程式的写法,以及对应的 INF 档设计方式。DDK 附有一个 INFEDIT 工具,以图形介面问答方式,让我们轻松做出INF 档。

Part3 的其馀各章(12~15)讲述不同型态之装置驱动程式的写法。Part4是对作业系统的扩充。在长达 57 页的第 16 章中,我最感兴趣的是 "File System API Hooking"一节,简单又强而有力。你可以利用这技术写一个 VxD,监视所有的档案动作。除了满足偷窥欲之外,商机不小,可做即时防毒、即时压缩、即时加密。

第 17 章的 DPMI 通常被放在一般系统程式设计书籍的最前面,Walter 逆向操作是因为,DPMI 的重要性已经远远降低了。我记得大约三年前,DPMI 是炙手可热的题目。当初微软主导制定 DPMI(INT31h 介面),是因为Windows 3.0 推出时 PC 市场上存在一种所谓的 DOS Extender 产品,能够将真实模式的 MS-DOS 程式不知不觉地切换到保护模式,取用其间广大的资源(最主要是记忆体)。Lotus1-2-3 3.0 就是这种结合了DOS Extender 而让人惊艳的商业产品。DOS Extender 为遂行这种威力,必须对整个系统握有监管的权(责),或是处於一个 VCPI(Virtual Control Program Interface)记忆体管理器的威力伞下。不幸的是 Windows 3.0 enhanded mode 接管了整部机器,将前两者全盘否定。为了「暂时」向主流低头,微软推导 DPMI,使 Extended DOS 程式得以顺利移植到Windows 3.0 的 DOS Box 中。如今,物换星移,DPMI 的存在,只是为了继续包容那些 16 位元的「Extended DOS 程式」而已。32 位元程式呢?不必,Win32 底下有所谓的 console 程式,方便得很,根本不需要DPMI 或 DOS Extender。至於 Win32 Windows 程式,使用任何软体中断都会失败,更不可能使用 DPMI。


Writing Windows VxDs and Device Drivers

我想你已经清楚,Walter 的书比 Matt 和 Jeffrey 又更低阶一些。了解虚拟机器和 VxD,对於了解 Windows 系统在 ring0 的活动状况多有助益,我已经决定在我开授的 Windows 作业系统课程中教导学生习作 VxD。如果你对这个主题有兴趣,我再推荐另一本好书:Writing Windows VxDs and Device Drivers (Karen Hazzah/R&D Books)。这本书台湾一直未见进口,非常辜负其美妙的插图和完整的观念叙述。该书已有第二版,购买时请注意。

writing-vxds.jpg (19239 bytes)
  


侯捷 2010-09-10 08:27:47

[新一篇] 到此躊躇不能去

[舊一篇] Programming 不必是自我虐待
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表