首先,这里讨论的Windows都是Win NT,也就是目前主流Windows的内核。当然,2003和Vista加入了大量.NET的因素,但其内核还是NT的。NT的起源是DEC的VMS,但是由于MS的商业策略,整个NT其实是一步步地搭出来的,在构建时以GUI为中心构架,CLI则仅仅作为一种辅助,于是VMS对进程的严格保护和封装并没有出现在NT上,更不同于VMS罕见的安全漏洞,NT成为一个漏洞百出而具有极高兼容性代价的系统。
于是,Windows本身不可靠的根源就在于──其核心的实现没有基于一个统一的理念(在统一的理念上,Unix的哲学是“一切都是文件句柄”,Macintosh则是“Mac界面方针”)。这样,随着NT积木一点点儿的搭建,相应的技术也就一点点儿地过时,基础性的概念也就越来越多,NT也就越来越冗大而危险。
这种最典型的现象就是NT对DOS命令行的兼容──NT的GUI实际上无法与残留的CLI共存,这也是NT中只有一个仿DOS命令行的“cmd”的原因。还有一个就是不存在统一数据对象(如Unix中的文件句柄)。而CLI被忽略以及统一数据对象的缺失又导致了:
为了实现并发程序设计以及网络的大量应用,Windows不得不引入更多的基础性概念──这就是为什么Unix系统下的用read/write就可以写出优美的程序而Windows下却要学习大量实际并不基础的基础性对象的原因(当时我们的OS上机就是基于Windows的,当时那个痛苦啊。。。)
大多数程序都没有CLI的功能,不能使用脚本调用,而必须使用脆弱而复杂的RPC来进行通信──众所周知,这正是大量程序漏洞和bug的产生根源
不存在通用的读写工具,各种程序的专有格式使得“兼容”成为一种妄想──而Unix的哲学是:文本化,于是Unix程序才如此的优美而小巧锐利
使用效率的低下──键盘永远比鼠标更有效率,而CLI永远都比GUI具有更强大的处理能力。
然后再来看一个OS性能判断中的三个重要因素:进程、文件系统和内存管理。
在进程上,我刚接触Linux时,着实被Linux中ps的结果吓了一大跳:系统中一共有上百的进程在执行!现在我正在用的系统中里则正运行着70多个进程,也要远远多于我用Windows时的大概30个左右的进程。但是,这并不标明Linux差于Windows,因为Windows生成进程的开销比Unix系统要高出一个数量级!同时Windows将一些系统的关键服务在进程的方面进行了集成,生成进程的开销更加昂贵。
在进程间通讯上,在OS课程上机时,我曾经比较过Linux(当时用的是RH)以及Windows(XP)中管道通讯的性能。结果无论是未命名管道还是命名管道,Linux都比Windows要快得多,大概有5倍左右我记得。
在文件系统上,Windows没有能力提供真正的多用户系统,在早期是因为Windows的商业策略──针对的是个人用户,不需要多用户的功能;而在后期,则更多地是因为为了保证向后兼容能力的遗留代码。于是,虽然Windows中存在访问控制列表可以管理用户权限,但大量的遗留代码使这种机制充满了碎小却足以致命的漏洞。而同样为了向后的兼容性,在各个GUI的客户端之间,其消息通讯机制不存在安全控制,这更是致命的。
在内存管理上,Linux的性能要显著地高于Windows。
首先,Windows实际上只为进程准备了不到2G的可用虚存空间,为了保证一定程度上的灵活性,Windows为程序员提供了多种使用虚存的解决方案,但这种灵活性以及为了DOS支持的兼容性,在内存管理上付出了极高的性能代价;而在Linux中进程则可以认为自己拥有真正的4G地址空间,而不用关心虚存是否提交物理存储等问题,比Windows要灵活得多。
同时在虚存,也就是内存的交换上,Windows的页面文件很难摆脱碎片化越来越严重的危险,这也是为什么VoptXp等硬盘碎片整理工具在Windows系统中不可或缺的原因;而Linux的内存交换除了专有的swap交换分区,我们还可以在普通的文件系统上建立没有空洞的文件来作为交换空间,更可以动态地增加交换文件,具有极高的灵活性。
当然,我们也不能忘记了Windows的特色──注册表以及dll
注册表是Windows存放各种配置数据的地方,而Unix的配置数据则存放在众多但清晰的dotfiles以及/etc中的数据文件中。由于注册表的设计特性,它导致整个系统非常地脆弱:某一个应用程序的故障就可能毁坏注册表而导致整个系统崩溃、甚至无法使用。同时,还有著名的“registry creep”,随着注册表的越来越大,其开销会托慢所有程序的运行。──于是传说中的“Windows无上大法”出现了:重启、重装,并且必须定期重装以保证系统的正常运行。
dll则是程序库,但是由于其版本的控制Windows没有提出良好的解决方案,导致了同样著名的“dll hell”配置问题──安装新的程序都可以任意地改变现有程序依赖的库文件(当然,有些程序会有提示,但你如何判断那个dll是不是有用的?),于是结果不是导致因为特定版本的系统库缺失而引起程序完全无法运行,就是导致dll文件越来越多。
同时,从内核的实现上看,为了追求性能,Windows NT3.5以后的版本将系统的GUI和真正内核一起塞进了同一个地址空间──这也是为什么说Windows没有GUI就无法正常运行。而进一步地,为了与Unix系列在服务器市场上竞争,新的Windows NT甚至将Web服务器也塞进了内核空间以在速度上与Unix竞争!搞笑地想一下,以后Windows的内核空间中会不会被塞进更多的东东呢?譬如MSN?
以上所说的这些所产生的内部边界漏洞,以及各种内部边界漏洞的相互影响,导致想在Windows上达到可靠是根本不可能的。因为非法的程序只需要随便用什么用户将一段随便什么程序的代码运行起来──譬如Office的宏?再譬如智能ABC的著名单击事件?──它就可能向任何运行的程序发送虚假的信息而打开缺口,而任何小小的缺口都可以成为控制整个系统的桥梁。
Windows的成功更多的在于TCP/IP时代到来之前就占领了大量的个人计算机市场,但其本身的缺陷导致了系统本质上的不可靠以及网络应用中的劣势──这也是MS为什么妄图推出.NET架构来拴住用户的原因。