上面说了这么多的课程和教材的定位,虽然出自我的切身体会,但对读者而言可能显得空洞,下面我们来看看现有综合性教材的一些共性问题。对于帮助学生理解操作系统如何工作这一目标而言,可以说大多数教材没有什么正面作用,教过、学过操作系统的读者可能都会有这样一个感受:为什么日常每天使用的操作系统学习起来会如此的抽象和陌生?这在很大程度上源自教材的内容组织和讲述方式。在此我细数传统教材的五宗罪:(1)内容过时:例如在处理机调度中大量介绍批处理时代的一些概念和算法;在设备管理中重点介绍通道以及独占式的设备分配;在内存管理中过多介绍连续内存管理等等。(2)解释不清:有一些过时的内容本身并不是太大问题,作为历史上曾经出现的技术当然可以介绍,但是应该解释清楚这些与现代操作系统无关,说明这些技术适用的特定情境,否则只能造成学生的迷惑。(3)内容缺失:缺少一些理解操作系统工作原理的关键知识,例如启动过程的说明、执行文件的载入机制、一些调度算法的执行时机等;另外一些需要的基础知识没有适当补充,例如CPU的虚地址保护机制一般都会超出前导课程的教学范围,但是不补充这些知识就根本不可能真正理解现代操作系统的内存管理机制。(4)衔接不畅:操作系统的不同管理功能之间是有机联系在一起的,但是大多数教材只是对每一部分单独介绍,并没有在需要衔接的地方进行说明;(5)人云亦云:综合性的操作系统教材,其主要内容常常是来自众多参考文献,如果作者在整合时并未基于自己的理解认真评判筛选,就可能出现对一些技术的分类和评价出现矛盾和偏差。目前的综合性操作系统教材或多或少存在上述问题,这也是本书编写中要竭力避免的。
本书将与传统教材有很大区别,这种特色源于采用的编写方法。我将根据个人对操作系统的理解来组织内容,围绕这理解操作系统工作机制的几个重要方面逐步展开。虽然最终成书的主干也会是围绕操作系统的几大管理功能,但是每一部分的概念引入方式、讲述重点都会不同;内容展开将采用“问题”引导的方式:首先提出需要解决的问题,讨论基本的解决思路,然后再引出相关的概念和算法;对于概念主要给出描述性信息而不是所谓“定义”,对于出现的算法则更加强调算法被调用的时机。为了避免受到现有教材的干扰,在写作过程中我会尽量避免参考任何现有教材,写作中的主要参考在线资源,尤其是Wikipedia和国内外一些技术博客,对于一些需要分析验证的技术细节,一般不去直接分析源代码,而是搜索相关技术文章,在别人分析的基础上基于自己的理解进行抽象和精简,并保留相关原始引用信息。阅读源代码是不得已的选择,因为效率太低。我个人认为如果没有专门开设阅读源码课程并且有老师能够给予针对性的指导,让学生自己摸索内核源代码是一件非常不负责任的事情,因为投入产出比实在太低。写这本书的目标其实也是想为愿意探索操作系统奥秘的学生提供一个相对的“捷径”,能够在不花费大量时间的情况下比较完整的了解操作系统,这样可以为他们自己选择是否在这个领域进一步深入提供一点参考,避免盲目地投入大量精力后空手而归。
什么人适合读这本书?如果你对计算机系统是怎样工作的觉得神秘而又心存好奇,那么这本书很有可能适合于你。如果你曾经学习过操作系统课程,并且很努力地想跟自己使用的系统加以对应,但是结果是一头雾水,那么这本书可以说就是为你量身定做的了,我会期望你在阅读不同章节时经常会发出“噢,原来如此!”的感叹;如果你是第一次接触操作系统课程,相信我,使用这本书会让你少走很多弯路;如果你为准备考研而重读操作系统教材,那么阅读本书一定大有收获,虽然研究生考试根本不会是本书的编写目标,但是鉴于研究生考试命题更加灵活并注重综合理解,本书对你的帮助很可能超过许多指定教材。
虽然我想要做到“深入浅出”,但是不要期望轻轻松松就能理解本书内容,操作系统本身的复杂性以及相关知识的广泛性决定了学习本书不会是简单的事情,要想真正理解还是需要做很多主动思考,如果能做一些验证性的实验更好,大多数的概念验证都可以使用现有工具软件或者编写简单的应用程序实现,少量需要编写内核模块,但总体来说本书不会要求对内核进行实质性改动来验证概念。阅读本书时一定要带着问题来读,如果没有弄清楚要解决什么问题一定会感觉迷失;相反,如果你很清楚问题是什么,那么理解问题的解决方法就会是顺理成章的。在学习操作系统原理过程中,当你遇到困难时不要忘记一个基本事实:你的研究对象不是一个自然界的怪物,而是一个人工生产的产品,别人能够为了解决问题而把它开发出来,你现在仅仅要去理解别人的解决方法,这不应该是多么困难的事情。我个人认为有效的学习方法是:尽力去理解每一个需要解决的问题,如果你认为自己已经完全理解了问题,不要急着往下看,利用自己已有的知识设想一个解决方案,然后再看书中的解决方法,看看有多大程度的偏差;如果偏差很大,大半说明你对问题存在误解,这时就应该回头再重读这一部分;如果偏差不大,那么这一部分已经进入了你的知识体系,可以不用再花更多的时间去抠细节了。通过这样的方式读完本书以后,你应该已经建立起一个比较完整的操作系统内核宏观架构,在此基础上你如果想在哪个方向上进一步深入,就可以阅读其他一些源代码导读类的书,针对特定功能深入探索。最后,可能有点多余地提醒一下,有内涵的专业书是需要反复读的;虽然本书尽可能按照初学者接触理解操作系统时的思路层层展开,但是不要指望一遍通读下来就能够很完整的理解本书的内容,有些章节如果理解困难,可以继续往后阅读,隔一段时间再回头看之前不懂的部分,一定会有不一样的理解,希望本书能做到让读者常读常新。相反,如果你第一遍阅读本书就能够完全理解本书内容,那你一定不是初学者,在操作系统领域有着非常深厚的专业功底,希望本书能得到你的共鸣。
学习操作系统原理除了要有正确的方法和思路,还需要掌握很多基础知识。在本科的教学体系中,操作系统属于比较高层的专业课,经常被列出的前导课程包括:程序设计语言、数据结构、汇编语言、计算机接口技术等,有些时候计算机组成原理也会被列入前导课程。这么多笼统的前导课程,到底哪些知识是学习操作系统所必需的呢?在此我尝试把需要的基础知识做一个简要说明,如果欠缺其中的一些部分,就很难理解本书中的相关内容。因为所要求的基础其实不是很具体的知识点,而且不同学校开设前导课程也会有差异,所以不按照课程来说明,而是简单地按照软件基础和硬件基础两个方面来说明。(1)软件基础:当然要有基本的程序设计思想,应该熟悉C语言编程,最好对于指针有比较好的理解(理解不深也没有关系,在内存管理的相关章节多下点功夫);要掌握基本的数据结构知识,对于线性结构的算法和链表式实现要熟悉,对于树、图结构概念理解清楚即可,最好能够理解散列(哈希)算法的基本思想和所起作用。(2)硬件方面:掌握基本的汇编知识,其实是要求对于机器指令级别的程序执行有所了解,学习过程中一般并不会有多少汇编语言编程;熟悉CPU的基本工作机制以及访问内存的方式(应该熟悉保护模式下的地址映射,不过一般读者大概都会欠缺这方面知识,所以本书会有补充);对于计算机外部设备的工作原理以及与CPU之间的协作方式有所了解。
上述这些基础知识都不需要读者记住很多细节,大部分只是要求能有一个基本的理解,当讲到相关术语时能够回忆起来大概情况即可。其实计算机的很多专业课就应该是这样,当学习时需要了解很多细节,才能真正理解课程的内涵,但是当学完一门课以后,一定要在自己的头脑中建立一个相对宏观、相互关联的知识集合,学习时的很多知识点是不需要记忆的,需要记住的是在什么情况下可能会有什么样的问题、能有什么样的思路去解决这些问题,这样当以后的学习和工作中确实碰到这些问题时,知道到哪里去寻找可供参考的解决方法进而自己解决问题。学习的过程一定是一个吸收+忘记的过程,只有把主干知识编织进自己的知识体系、把细节知识排除在外,才是你继续学习新知识的理想状态,否则太多的细节知识不仅可能阻碍学习新知识,而且可能由于形成思维定势而错过一些革命性的新技术。如果你曾经看过金庸的《笑傲江湖》,书中风清扬教给令狐冲纷繁复杂的独孤九剑招式,然后要他尽力“忘掉”,从而只记得“剑意”而不受招式的束缚,这大概就是我所说的意思了。这个状态的另一种说法是“融会贯通”,要想达到这个境界需要自己持续的“悟”,别人是教不出来的,“悟”的过程说起来好像有点玄妙,其实每个人的学习过程中或多或少都会有这样的经历,在学习过程中应该追求这种状态,使得所学到的知识都成为构造自己知识体系的原材料,而不要拘泥与一些具体知识的细节。“悟”的过程还有一个关键的因素,就是批判性思维,读书一定要有思辨和评价的过程,尽信书则不如无书;如果对于一些知识点始终觉得无法融入自己的知识体系,不应一味地尝试修改自己的已有知识,也许应该怀疑书的作者是否犯了错误,就我个人经验而言,这种情况并不在少数。本书也不例外,一定会存在一些以偏概全的情况,希望读者能够对书中的内容提出不同的看法。
作为前言,好像写的有点多了,因为在尝试写前言的过程也是自己整理编写思路的过程,希望在前言中让读者了解一些最重要的信息:这本书有什么不同、为什么会有这些不同,自己是否适合阅读这本书。书最终成稿后再重新整理一下吧,后面要进入实质内容的写作了,预计是一个艰苦而漫长的过程,为了保证质量和自己编写思想的贯彻,我不准备假手学生做工作,很多内容还需要编程验证。不过我不赶时间,这个想法都已经撂了几年了,再写个一两年也没什么,我只是想写一本对得起自己、以后在任何时候再回头看都不会感到羞愧的作品。