在学习Linux内核代码的过程中,定会参考很多书籍以及网路资源,但是并不是所有的书籍和资源都能够帮助你前进,或者说是能够将你引导向正确而高效的道路。
在学习的一些阶段可能会需要不同的书,比如在第一个阶段,一些基本的书籍都是可以参考的。这个阶段的书籍非常多,比如《鸟哥的linux私房菜》,它介绍了Linux系统的基本概念和使用。《高级Bash脚本编程指南》可以说是学习Shell的利器,翔实的示例和解释足以让你成为Shell专家。另外可以在Linux平台架设一些常用的服务器等以增加实践。
由于大部分人在大学期间都学习过C语言,所以在学习的第二阶段依然可以把那本经典的谭浩强读本放在手边作为参考手册。《Linux C编程一站式学习》这本书在介绍标准C的同时则倾向于Linux平台的编程:网络编程,ELF格式解析,链接的原理和Makefile。此时如果不提大名鼎鼎的《UNIX环境高级编程》和《UNIX网络编程》这两本书,一定会遭到抗议。尽管书名包含UNIX,但是由于Linux是类UNIX的系统,所以这两本书同样适用于Linux环境。
《UNIX环境高级编程》被誉为UNIX编程“圣经”,并且一版再版。它的首席作者W.Richard Stevens是国际知名的UNIX和网络专家;受人尊敬的计算机图书作家;同时他还是广受欢迎的教师和顾问。Stevens先生不幸逝于1999年9月1日。UNIX操作系统的原作者Dennis Ritchie对该书的评价是“公认的优秀、匠心独具的名著”。再多的赞誉都不为过,因为除了参考系统函数或者glibc库函数的文档或者直接查看源码能够获取比该书更全面的信息外,似乎别无他法。如果你能够在某些网站或者书籍获取到比该书更详尽的描述和分析,那么把它作为参考一定不会错。非常喜欢这本书首页上的“Standing on Shoulders of Giants”——站在巨人的肩上。
《UNIX网络编程》同为W.Richard Stevens的另一部名著,它弥补了《UNIX环境高级编程》在网络编程方面叙述的不足,与该书享有同样的地位。该书的最新版本由世界著名网络专家再次修订,添加了IPv6,SCTP以及密匙管理相关的内容。所以值得庆幸:这两本书都没有因为Stevens先生的离去而失去时代的活力。
杰出人物的成就总是在让人景仰的同时,令人不由自主的惊叹。《TCP/IP 详解》(三卷本)作为了解当前盛行世界的因特网原理的圣经级著作,也同样出自其手。“Richard Stevens以他的写作风格和作品,在TCP/IP编程领域竖立起一座丰碑,令其他作者高山仰止,心向往之”。
在这里一气儿介绍了Stevens先生的这三本书,应该没有人会非议。如果你在一些Linux编程或着网络方面的资深著作中的参考书目中没有找到这三本书的名字,那确实有点不可思议。
在参考以上书籍,并在个人努力和工作经验积累的情况下,到达第三个阶段是水到渠成的事。这似乎是一个关键的时刻:要么继续留在原地,要么进入一个完全不同的领域。关于探索Linux内核代码的书籍这些年来已经相当繁多。如果粗略的对它们进行分类,大概如下:
一些书籍可能会大量的引用代码,但是不对该功能模块的原理和细节进行详述,最多在源码中给出一些翻译后的注释。这类书籍适合做参考,却不适合用它来系统的学习内核原理。否则很快就将进入“一鼓作气,再而衰”的境地,因为越来越多的疑问将耗尽你的激情,最后除了头脑混乱外,很可能得出学习内核太难的结论。这里对这类书做了一定的批判,但是它们依然不乏作为参考资料的价值。在最近一段时间的相关出版物中,这类书籍已经越来越少,而一批质量较高的国内书籍开始呈现出来。
有些书籍单独针对内核特定的区域或者说子系统来讲解,比如内核驱动,网络实现等。这类书籍针对性较强,对细节比较注重,能够对一些问题分析的较为透彻,另外一个优点就是这类书往往比较薄,让人容易接受。当然了这也就意味着它不能给你在另一个内核功能领域以有效的指导。这类书的典型代表有:《深入理解LINUX网络内幕》,《深入理解Linux虚拟内存管理》,《Linux设备驱动程序》和《Embedded Linux Primer》。更确切的说后两本并不是讲解内核原理的,它们针对的是内核的应用,所以在选择时应该加以区分,但是《Essential Linux Device Drivers》这本书有取代《Linux设备驱动程序》之势,它补充了驱动相关的内核原理部分。
还有一类书,这类书不太好对它进行分类,它们对深入理解底层硬件相关部分的基本原理帮助颇大,但毕竟描述的内核版本和当前的2.6内核版本相去甚远,比如对0.1版本的分析,如果单从这些资源来学习当前的内核版本似乎有点“舍近求远”。它们的真正价值在于分析内核的角度,也即它们没有随波逐流的去跟随已有的著作,而是独辟蹊径,从另外一个侧面揭示Linux的远古面纱。这种书籍的代表有《Linux内核完全剖析》和《Linux内核设计的艺术》,从后者的内容可以看出它应该能代表当前国内在Linux领域的部分研究水平。
好了,如果在这一领域没有一些重量级的选手出场一定说不过去。《深入理解Linux内核》和《Linux内核设计与实现》,这两本书分别被简写为ULK和LKD,它们应该算是一个重量级的。并且论述的方式非常像操作系统原理,但是是结合Linux的系统原理。把它们作为教材是非常之好。ULK可以说就是Linux版的系统原理,从行文风格,知识点的切入方式基本是属于学术派:首先是提纲挈领的简介,然后是细分的要点详述,进而引述少量的代码。LKD与ULK非常相似,但是很明显的感觉到它对代码的引用要多,实践性更强,比如它会谈到内核的代码结构,编译,调试,glibc库以及Linux的代码风格等,属于实践派,但又不完全,因为它比实践的书籍多了理论的介绍,但是代码引用的程度又太少,如果完全跟随它来通过开发板实践相关的功能子系统,可以说能够摸着石头过河的时候非常少,大部分的关键代码都无法从书中找到蛛丝马迹。另外由于它页数的限制,很多内核功能的细节都被忽略掉了,虽然第三版的英文版已经发行,除了最后一个章节的内容有大的改变外,基本延续了前版叙述的知识范围。所以它渐渐有被后来者《深入Linux内核架构》LKA代替的危险。
书籍名称 | 作者 | 出版时间 | 内核版本 |
Understanding the Linux Kernel, 3rd Edition(ULK) | Daniel P. Bovet, Marco Cesati | November 2005 | 2.6.11 |
Linux Kernel Development, 3rd Edition(LKD) | Robert Love | June 2010 | 2.6.34 |
Professional Linux Kernel Architecture(LKA) | Wolfgang Mauerer
| January 2008 | 2.6.24 |
Linux内核经典书籍
ULK基本是属于学术派的著作,两位作者都是学府内的教授,他们自然在有意无意中会更专注操作系统的原理和算法,而或多或少限制对代码实现的论述。所以它属于通用操作系统原理著作但又向Linux实现靠近的理论论述的一种过渡,由于ULK将所有篇幅放在了Linux对操作系统的实现上,所以它在理论层面的论述可以说鲜有挑战者。总体来看ULK和LKD之间的关系,很容易发现LDK的出现是用来弥补ULK在论述实践这一块的缺失,但是不知为什么LKD对实践的论述又不彻底,反而造成了一种有点儿尴尬的骑墙势。
不妨做如下的推理假设:如果在多年前,那时候内核代码的维护还基本在一个有限的圈子里,这些人都是计算机黑客或者是内核代码的狂热爱好者,他们完全有能力维护好各自负责的代码部分。但是随着功能的增加,代码量也与日俱增,而代码量的增加会以非线性的方式影响代码的复杂度,这导致对代码的把握非常不易,维护起来的难度可想而知。直至今日,内核代码的维护人员有点青黄不接。所以合理的猜测是:LKD最初出现时是为了给内核开发的新手做一个入门式的引导,因此它花了几章的篇幅在介绍Linux代码结构,编译,调试以及代码风格上。
LKA是由德国Wolfgang Mauerer完成的。所以它的原版是德文版,而英文版的出现已经到了2008年。这本书在国内推出的时间则推迟到了2010年的后半年。尽管笔者只看了这本书的若干章,但可以毫不扩张的说,它是在Linux实践领域进行相对全面的论述的集大成者。看一本书对知识点的把握深度和细度,只要看它对Linux内核中最复杂的内存管理机制的论述就可以了,比如它对内存区类型ZONE_MOVABLE的作用的叙述,在大多数的类似书籍中都难以找到对它的详细描述。另外一点值得肯定的是,它在内核代码的应用中有非常好的连贯性,使用开发板跟随它的论述进行实践验证是可行的,摸着石头过河是现实的了。由于深度细度以及代码连惯性两方面的要求,尽管这本书只有十九章,中文版的页数已经达到了一千多页。总结:这本书是用来研究内核的,它并不太注重对内核的使用,而大多数人可能是为了学习内核驱动的开发,这个LDD3或者ELDD就可以了,使用LKA反而是南辕北辙。但是如果你想洞悉Linux对操作系统的实现,那么选择它基本上没错了。
尽管LKA比LDA具有很大的优势,它也不是完美无瑕,一些地方可能翻译得不够准确,比如内存管理中对页和页帧的使用,有些混乱。另外一些句子可能翻译的不够恰当,比如P23页的“对于后者来说有大量的调试器可用,而对于后者来说”改为“而相对于后者来说”更为贴切。另外原版作者可能主要在x86上进行实验和研究,所以有些地方可能适用于x86架构,但并不适合所有的平台。例如P111中的“node_start_pfn在UMA系统中总是0”,诚然x86的CPU对物理RAM的地址从0开始分配,但是ARM的CPU就不尽然,它通常都不是从0开始。P137中“减去0Xc0000000,则可以获得对应的物理地址”,但在ARM上应该还要加上一个物理地址的偏移。尽管如此,瑕不掩瑜。
未知何朝何代,武林中出现了名震天下的两大流派:剑宗和气宗。它们吸取了中原各大门派武术之精华,适时有两少年各入两宗,相约十载一战。
两人各拜其师,砥砺寒暑,未敢懈怠。光阴荏苒,白驹过隙;十载春秋,弹指一挥。是日,会稽山下,只见一人仙风荡漾,一人剑气浩然。日出而战,披星而息。剑出。
廿十载,气完胜。又十载,日出而战,而三日不能息!何也?气中有见,剑中有气,阴阳相合者也。
在经过了一番“讨价还价”之后,似乎找到了学习内核原理的最佳组合了:理论与实现,ULK和LKA,似乎把它们缩写成ULKA更好,如此则阴阳相合,关于书也就说到这了!
最后的啰嗦:如何看书?是一气看完?还是分章节,一一攻破呢?显然是一一攻破要好的多,所有章节看下来的周期太长,难于把握。实际上还要根据难易程度来决定,有些章节需要非常细心的研读。另外要注意实践和理论一定要结合,比较简单的功能实现,可以先实践,也即先循着LKA讲的顺序看看代码,然后自我分析,接着结合ULK的理论,从全局把握;比较复杂的功能模块,则可以先看ULK理解基本的系统原理,然后再结合LKA进行实践。本质上需要把90%的时间花在这两本书和在开发板的实践上,只有通过它们还不能完全理解的情况下,再去参考其他的书籍和资源,这可以保证学习的效率。
Linux系列:linux学习之路(入门类、编程类、内核类、工具类……)
入门类
一直认为,在一个系统上学习开发之前,首先需要熟悉这个系统的使用。鉴于天朝的国情,绝大部分人第一个接触的操作系统就是Windows,因此对于这绝大部分人来说,如果要学习Linux开发,学会使用这个系统都是必不可少的一个环节。
现在的Linux初学者是幸福的,随着Linux桌面环境越来越易用,入门一个新的系统是非常容易的事情。虽然命令行对于提高工作效率更加有效,但 我们完全可以把熟悉命令的过程放到日常使用中进行。无论学习什么知识,在实践中学习都是高效而且有趣的。在这个阶段,我们也未必一定需要书籍。现在很多 Linux发行版的Wiki写得都非常详细,在使用某一种发行版时找到相应的Wiki阅读查询就可以了。而且,桌面环境变化太快,关于桌面的介绍类书籍几 乎都没有必要看,这类书籍大多刚一出版就过时了。
那入门类书籍里哪些比较有价值呢?我比较推荐涉及的技术相对比较稳定的书。比如,Linux基本的体系结构和命令一般都是经久不变的,甚至从上古时期的Unix开始就没太多变化,这类书籍讲解的知识也是以后大幅提高我们的生产力的基础。比如《鸟哥的Linux私房菜》,比如《Unix Power Tools》(中译名是“UNIX超级工具”),或者是为Linux+认证考试准备的《Linux+ Study Guide》。当然,这一类书籍其实都不必精读,快速浏览之后作为工具书备查就可以了。
编程类
类Unix系统的编程书籍里,最经典的莫过于简称为APUE的《Advanced Programming in the UNIX Environment》 (译名是“Unix环境高级编程”),这本书被广大Unix程序员(包括Linux)捧为“圣经”。借用葛大爷的广告词:“这就像进馆子一样,一条街上, 哪家人多我进哪家”。APUE对类Unix系统的编程接口讲解的非常全面详细,对于这本书,我们不仅要精读,还应该放在案头常备。
但是,APUE对于Linux编程初学者似乎稍深了一点,而且很多细节在Linux中并不会用到。讲述Linux编程的书籍里,《Advanced Linux Programming》应该更加适合初学者。不要被书名中的“Advanced”吓到,书里的内容还是很容易理解的。看完这本书再看APUE应该效果会更好。
如果要开发GUI程序,上面两本书就无能为力了。在Linux世界里,最常用的GUI Toolkit是GTK+和QT。
GTK+的书籍并不多,在线文档只适合查阅,并不是一个完整的学习体系。《Foundations of GTK+ Development》是其中很不错的一本书,喜欢GTK+的开发者可以拿来作为入门书籍。
相对来说,QT的书籍就很丰富了,这和QT具有良好的跨平台能力有很大关系,QT的书籍并不只是写给Linux程序员看的,在Windows和MAC OSX下同样可以使用QT开发程序。比较值得一看的QT类书籍有《C++ GUI Programming with QT4》、《Foundations of QT Development》、《The Art of Building QT Applications》,这三本都比较适合QT初学者阅读。另外,《Advanced Qt Programming》会介绍到QT一些比较高级的用法,适合有一定QT基础的读者阅读。
内核类
对于Linux内核或者设备驱动的开发者,最全面最直接的学习资料一定是Linux内核代码及其文档。Linux内核的发布周期很短,相关书籍的出 版完全跟不上脚步。但随着内核代码的日益庞大,学习曲线越来越陡峭,入门者又非常需要书籍来作为指导,这确实是非常矛盾的事情。所幸,很多Linux内核 技术作家也是很勤奋的,经常会更新自己的作品。就像Robert Love,以2.6内核为蓝本的《Linux Kernel Development》已经更新到第三版了。LKD是非常适合内核初学者阅读的一本好书,对它的评价可以引用陈莉君老师的译者序:
相对于Daniel P. Bovet 和 Marco Cesati的内核巨著《 Understand the Linux Kernel 》,它少了五分细节,相对于实践经典《 Linux Device Drivers》,它多了五分说理。可以说,本书填补了Linux内核理论和实践之间的鸿沟,“一桥飞架南北,天堑变通途”。
谢谢陈老师,她的译者序帮我引出了另外要谈到的两本经典书籍,对,就是《Understanding the Linux Kernel》和《Linux Device Drivers》。对于这两本书,如果要挑它们的缺点,我只能说,内容有点老,很多知识点都需要更新了,除此之外,我要说的是,是它们把我带上了内核驱动开发这条路上来,当然,还有LKD。
最近,我又发现一本分析Linux内核的优秀书籍,就是《Professional Linux Kernel Architecture》。这本书我目前正在读,写得非常好,而且因为此书相对较新(只是相对,2.6.24内核在现在看来也很老了),没有看过ULK的同学可以直接看这本书。
工具类
工欲善其事,必先利其器。进行Linux开发,相关工具还是需要熟练使用的。比如,GNU Tool Chain、自动构建工具、编辑器、版本控制工具等等。
这里有一本包罗万象的书,叫做《Handbook of Open Source Tools》,书中介绍了各种各样的开源工具,可称之为开源技术的总决式。这本书试图面面俱到,因此并不深入,粗读即可。
GNU Tool Chain参考Redhat的《The GNUPro Toolkit》已经足够了,如果单独把makefile拎出来,还可以参考《Managing Projects with GNU Make》。
自动构建工具可以参考《Autotools》。如果您准备使用cmake,推荐cjacker的《Cmake实践》。《Mastering CMake》据说是cmake的权威书籍,但一直无缘得见啊。
说到编辑器,在Linux里最著名的莫过于Vim和Emacs,关于这两者的背景,可以去看看《为何Emacs和Vim被称为两大神器》。我几乎没用过Emacs,曾经在当当做活动时花9块钱买了一本《学习GNU Emacs》,有这本书作为Emacs的入门我想应该够了。Vim是我经常使用的编辑器之一(另一个是Kate,最初喜欢上Kate的原因之一就是它提供了Vim编辑模式),相关的书籍有两本值得一读:《A Byte of Vim》和《Hacking Vim 7.2》,但是对于初学者,首先跟着Vim自带的vimtutor练习效果会更好。
Linux下的版本控制工具很多,有传统的Subversion,也有现在非常流行分布式工具如Git等。Subversion可以参考这本《Version Control with Subversion》,Git可以参考《Version Control with Git》或者《Git Internals》或者《Pro Git》。
其它
除了以上几个类别,还有一些书籍值得推介。
比如《The Art of Unix Programming》,主要介绍了Unix系统领域中的设计开发哲学、思想文化体系以及社群文化等,覆盖面非常广。书中的一些内容和《Revolution OS》有相似之处,大家可以自己印证一下。对于这本书,我们也完全可以把它当做小说或者历史书来看,可以躺在床上看,也可以瘫在沙发上看,或者像怪怪那样坐在马桶上看,总之,不必一定要端坐在书桌前。
《Computer Systems: A Programmer's Perspective》 很多人都推荐过,这是一本非常经典的计算机体系方面的教材。CSAPP的内容基础全面,讲解简明扼要,易于理解,仔细读完之后对理清计算机体系结构甚至是 Linux内核都非常有帮助的。虽然中文名被译为《深入理解计算机系统》(这个译名很不贴切),但相比之下,为什么会让人感觉国内的同类教材更加“深奥” 呢?也许,这就是作者功力的差距吧。