linux内核设计与实现
一本很好的介绍linux 内核的书,非常值得一看!前言在我刚开始有把自己的内核开发经验集结成册,撰写一本书的念头时,我其实也觉得有点头绪繁多,不知道该从何下手。我实在不想落入传统内核书籍的窠臼,照猫画虎地再写这么一本。不错,前人著述备矣,但我终归是要写出点儿与众不同的东西来。说实话,这确实让人颇费思量。后来,灵感终于浮现出来,我意识到自己可以从一个全新的视角看待这个主题。开发内核是我的工作,开发内核是我的嗜好,内核就是我的挚爱。这些年来,我不断搜集与内核有关的奇闻轶事,不断积攒关键的开发诀窍,依靠这些日积月累的材料,我可以写一本关于开发内核该做什么和不该做什么的书籍。本质上,这本书仍旧是描述 Linux内核是如何设计和实现的,但是写法却另辟蹊径,所提供的信息更倾向于实用,通过本书,你就可以做一些内核开发的工作了—并且是使用正确的方法去做我希望读者可以从这本书中领略到更多 Linux内核的精妙之处(写出来的和没写出来的)也希望读者敢于从阅读本书和读内核代码开始跨越到开始尝试开发可用、可靠、清晰的内核弋码。当然如果你仅仅是兴致所至,读书自娱,那也希望你能从中找到乐趣。不管你学习Lnux的意图是什么,我都衷心地希望你能喜欢我的书。作者的体会开发 Linux内核不需要天赋异秉,不需要有什么魔法,连Unix开发者普遍长着的络腮胡子都不一定要有。内核虽然有一些有趣并且独特的规则和要求,但是它和其他大型软件项目相比,并没有太大差别。像所有的大型软件开发一样,要学的东西确实不少,但是内核开发并不神秘,也不深奥, Linux内核开发者其实并不需要付出比其他开发者更多的努力。认真阅读源码非常必要, Linux系统代码的开放性其实是弥足珍贵的,不要无动于衷地将它搁置一边,浪费了大好资源。实际上就是读了代码还远远不够呢,你应该钻硏并尝试着动手改动一些代码。寻找一个bug然后去修改它,改进你的硬件设备的驱动程序,总之要有的放矢地做一些实际工作!只有动手写代码才能真正融会贯通。读者范围夲书是写给那些有志于理解 Linux内核的软件开发者的。本书并不逐行逐字地注解内核源代码,也不是指导开发驱动程序或是内核AP的参考手册(如果存在标准的内核API的话)。本书的初衷是提供足够多的关于 Linux内核设计和实现的信息,希望读过本书的程序员能够拥有较为完备的知识,可以真正开始开发内核代码。无论开发内核是为了兴趣还是为了赚钱,我都希望能够带领读者快速走进 Linux内核世界。本书不但介绍了理论而且也讨论了具体应用可以满足不同读者的不同需要。全书无处不围绕着理论联系实践,并非一味强调理论或是实践。无论你硏究 Linux内核的动机是什么,我都希望这本书都能将内核的设计和实现分析清楚起到抛砖引玉的作用。因此,本书覆盖了从核心内核系统的应用到内核设计与实现等各方面内容,我认为这点很重要。例如第6章讨论的是下半部机制。其中分别讨论了内核下半部机制的设计和实现核心内核开发者会感兴趣),随即便介绍了如何使用内核提供的接口实现你自己的下半部(这对设备驱动开发者很有用处)。其实,我认为上述两部分内容是相得益彰的,虽然核心内核开发者主要关注的问题是内核内部如何工作,但是也应该清楚如何使用接口;同样,如果设备驱动开发者了解了接口背后的实现机制,自然也会受益匪浅。这好比学习某些库的API函数与研究该库的具体实现。初看,好像应用程序开发者仅仅需要理解APⅠ——一我们被灌输的思想是,应该像看待黑盒子一样看待接口。而另一方面,库的开发者也只关心库的设计与实现。但是我认为双方都应该花时间相互学习。能深刻了解操作系统本质的应用程序开发者无疑可以更好地利用它。同样,库开发者也决不应该脱离基于此库的应用程序,蒙头开发。因此,我既讨论了内核子系统的设计,也讨论了它的用法,希望书能对核心开发者和应用开发者都有用我假设读者已经掌握了C语言,而且对 Linux比较熟悉。如果读者还具有与操作系统设计相关的经验和其他计算机科学的概念就更好不过了。当然,我也会尽可能多地解释这些概念但如果你仍然不能理解这些知识的话,请看本书最后参考资料中给出的一些关于操作系统设计方面的经典书籍。这本书很适合在大学中作为介绍操作系统的辅助教材,与介绍操作系统理论的书相搭配。对于大学高年级课程或者硏究生课程来说,可直接使用本书作为教材本书的组织形式本书循序渐进地揭示 Linux内核的结构,也就是说,毎一章都尽可能地为下一章做铺垫,因此本书是有序地组织各章内容的。但是,这并不是说读者就不能自由地查阅相关章节获取感兴趣部分的参考资料。恰恰相反,我尽力使得各章内容都相对独立,内容尽可能完备,那些对内核基本情况已经有所了解的读者,完全可以按照自己的实际需要直接阅读相关章节。第1章介绍了操作系统、内核、Unx和本书的主角 Linux。如果你读过有关UniX、Liux或其他操作系统的书籍,你定会发现许多似曾相识的内容。第2章讨论了进程的内核抽象,以及进程如何被创建、销毁和管理。由于操作系统最终目的是让用户运行程序,所以这章是最基础的内容。第3章继续讨论进程的调度,在像 Linux这样的抢占式多任务的操作系统中,内核负责调度进程的执行。这一章从进程调度的概念逐步深入到 Linux进程调度程序的实现细节第4章讨论系统调用,它是应用程序访问内核的标准机制。这一章详细讨论了系统调用的原理系统调用处理程序的设计和如何实现一个新系统调用。第5章讨论了中断和中断处理程序。第6章讨论了下半部和其他推后执行机制。这些技术在编写设备驱动程序和管理设备时是必不可少的。接下来,我用两章篇幅着重介绍同步和锁的概念:第7章讨论了同步和并发,附带介绍了竞争条件和死锁概念,同时提出了对它们的解决方法、比如使用锁定机制。第8章介绍了内核为了维护同步性提供的实际接口,比如自旋锁和信号量:第8章在第7章的基础上对内核锁机制进行了进一步探讨。第9章讨论内核时间流,这一章讨论时对操作系统的意义和表示形式,另外还介绍了内核如何管理系统时间。最后介绍了内核定封器的实现和使用方法。第10章讨论了內存管理和如何在内核中分配内存,第11章讨论虛拟文系统(VFS),它为用户空间提供了通用文件接I,是粘合硬件、文件系统、用户空间层。第12章讨论块IOXI层,它是内核为了管理硬盘等硬件设备提供的子系统。这层对內核提高块设备的性能至关重要。第13章讨论进程地址空间和进程的虚拟内存。第14章讨论了页高速缓存和如何执行页回写操作。页缓存是 Linux內核的主要内存缓存—通过内存缓存可以减少磁盘访问频率,提高系统性能。第15章讨论调试內核的技术,调试内核被公认为是内核编程难于用户程序编程的主要内容,因为不能像对待用户空间的应用程序那样不加限制地对待内核。此章内容包含了调试内核的基本方法,还有一些可以利用的附加技术(这里并没有标准的调试器),以及一些可能带你走出困境的调试技巧。第16章讨论了可移植性和各种体系结构的特殊之处,它可以帮助你编写可以在任意体系结构上运行的优良代码。可移植性是一个有趣的话题,因为它能跨越体系结构的差异。另外由于 Linux是个高度可移植性的操作系统,所以在编写高质量内核代码时必须考虑到这一点才能满足跨体系结构运行的要求。第17章讨论了生成补丁和给系统打补丁,以及如何参与 Linux内核社区等问题。本书的最后一部分是4个附录和参考资料。附录分别包含了内核链表的实现、单处理器接口、内核随机数产生器和算法复杂度。参考资料列举了许多相关主题的阅读资料。本书的相关网站我维护了一个包含本书相关信息的网站:htt:tec9. net/rm/ kernel book./。其中包括本书的勘误表、内容扩展和修改,同时也提供了未来重印和再版的信息。希望读者多到这个站点看看感谢与其他作者一样,我决非是一个人躲在山洞里孤苦地写出这本书来的,我能最终完成本书原稿是与无数建议和关怀分不开的。仅仅一页纸无法容纳我的感激,但我还是要衷心地感谢所有给予我鼓励、给予我知识和给予我灵感的朋友和同事。首先我要提到的人是我的编辑 Kathryn Mohr女土,感谢她对我的支持和建议。是她鼓励我开始写作此书,并且从撰写提纲到截稿的整个过程中,都给予我无私的帮助和指导。除她以外,我还要感谢Sams出版社负责本书的小组的其他几个成员,感谢他们给予我的帮助,他们是 Chip gardner、 Scott Meyers和 George Nedef我的技术编辑 Zack brown也是我需要倍加感谢的人,他认真、淮确地校对我的书稿,并给了我许多宝贵的意见。Zack独到的洞察力是至关重要的。他的工作称得上完美,如果书中仍遗留有错误,那责任只由我自己承担,绝对和Zack先生无关许多内核开发者为我提供了大力支持,回答了许多问题,还有那些摆写代码的人,本书正是由于有了这些代码,才有了存在的意义。他们的名字是: Alan cox、 Greg KrohHartman、 William irwin、 Daniel Phillips、 David miller、 Partrick mochel、 Ingo Molnar、Andrew morton、 Rik van riel和 Linus Torvalds还有许多人在我写作期间不断鼓励我,在方方面面都给予我关怀。这本书也凝聚着他们的爱心。他们是: Paul amici、 Richard erickson、 Dustin hall、 Jack handy、 Joyce HawkinsDoris love、 Jonathan love、 Linda love、 Dustin mounce、 Randy o’Dowd、 SalvatoreRibaudo和他了不起的妈妈、 Chirs rivera、 Larry rivero、 Jeremy Van Doren和他的全家Steve Weisberg、 Helen whisnant等。XII我述要感谢我的雇主, MontaⅤista软件公司以及那車的同事,特别是一直支持我的 ScottAnderson和 Mark orvek感谢 Marlena,没有她我不可能取得什么成就最后,我要感谢我的父母,感谢他们的爱。内核黑客万岁Robert loveGainesville, Florida读者反馈方式本书的所有读者都是我们尊敬的批评者和评论者,我们渴望获得你的意见,我们希望了解我们所做的哪些工作是正确的,哪些工作可以做得更好,你们希望我们出版什么内容的书以及任何对我们有帮助建议。你可以直接发 email或写信给我,告诉我这本书哪里你喜欢,哪里你不喜欢—一我们如何提高书的质量。请注意我无法回答你们关于书中主题的相关技术向题,我接收的邮件太多,我难以一一回答。请在写信时注明书的作者和书中的主题,同时也请写清楚你的姓名、电话和emai地址。我一定会详细地阅读你的评论,并且与书的作者和编辑交流。Email:opensourcesamspublishing.com通信地址: Mark taberAssociate PublisherSams publishing800 East 96th StreetIndianapolis, Indiana 46240 USA如果希望了解该书的更多信息和Sams出版社的其他出版图书,请访问我们的网站www.sam-publishing. com。可以在搜索框中输入ISBN(除去连字符)或书的标题来寻找你要找的书。关于作者Robert love很早就开始使用 Linux,而且一直活跃于开源社区。最近,他受聘于Monta vista软件公司,作为软件工程师,继续做开发 Linux内核的工作他的内核项目包括进程调度程序、抢占式內核,还有ⅤM和多任务处理性能优化。他负责XIII维护的另外两个开源项目是 schedutils和 props.:除此之外,他对内核有不少精彩评论,而且他还是 Linux journal/杂志的特邀编辑。目前,他居住在佛罗里达州的 Gainesville,爱好摄影以及美食。关于技术编辑Zack brown是著名的时事通讯 Kernel traffic的发起人和作者之一,该杂志起源于1999年,它跟踪 elinux內核开发邮件列表的最新事件。他定期提供 Linux journal的“dif-u”服务。并为德国 Linux magazin杂志撰写“ Zacks Kernel news”。他在旧金山生活和工作目录出版者的话3.1策略专家指导委员会3.1.1IO消耗型和处理器消耗型的进程…26译者序3.1.2进程优先级26序言31.3时间片26前言3.14进程抢占27第1章Lnux内核简介…31.5调度策略的活动281.1 Linux简介3.2调度算法282操作系统和內核简介32.1可执行队列281.3 Linux内核和传统Unx内核的比较3.22优先级数组301.4 Linux内核版本……323重新计算时间片1.5 Linux内核开发者社区32.4计算优先级和时间片6内核开发的特点63.2.5睡眠和唤醒…341.6.1没有libc库326负载平衡程序…361.6.2GNUC∴∴33抢占和上下文切换…381.6.3没有内存保护机制833.1用户抢占381.6.4不要轻易在内核中使用浮点数93.3.2内核抢占39L.6.5容积小而固定的栈934实时166同步和并发35与调度相关的系统调用401.6.7可移植性的重要性1.7编译内核3.1与调度策略和优先级相关的系统调用408小结第2章进程管理3.5.2与处理器绑定有关的系统调用…42.Ⅰ进程描述符及任务队列14353放弃处理器时间2.1.1分配进程描述符…74第4章系统调用2.12进程描述符的存放4.APⅠ、 POSIX和C库43152.1.3进程状态164.2系统调用…4421.4设置当前进程状态4.2.1系统调用号…21.5进程上下文17422系统调用的性能………………452.2进程创建∴194.3系统调用处理程序452.2.1写时拷贝943.1指定恰当的系统调用2.2.2 fork(………194.3.2参数传递462.2.3 vfork()……2044系统调用的实现4623线程在Liux中的实现204.5系统调用上下文4824进程终结…245.1绑定一个系统调用的最后步骤2.4.I删除进程描述符34.5.2从用户空间访问系统调用2.4.2孤狐儿进程造成的进退维谷45.3为什么不通过系统调用的方第3章调度25实现51XV第5章中断和中断处理程序53第8章内核同步方法51中断…538.1原子操作…9752中断处理程序8.1.1原子整数操作…53注册中断处理程序………558.1.2原子位操作54编写中断处理程序……568.2自旋锁54.1共享的中断处理程序578.2.1其他针对自旋锁的操作…02542中断处理程序实例…588.2.2自旋锁和下半部543中断上下文8.3读-写自旋锁·105.5中断处理机制的实现8.4信号量…l055.6中断控制……6384.1创建和初始化信号量10656.1*止和激活中断63842使用信号量07562禁止指定中断线∴…648.5读-写信号量563中断系统的状态86完成变量∴∴109第6章下半部和推后执行的工作…678.7 BKL1096.1下半部6788seq锁l10611为什么要用下半部……688.9棼止抢占6.1.2下半部的环境688.10屏障…62软中断70第9章定时器和时间管理71S621软中断的实现………9.1内核中的时间概念…6.22使用软中断92节拍率:Hz166. 3 Tasklets身晕鲁·最9.3 liffes.…11963.1 Tasklets的实现749.3.1jffs·内部表示…1196.32使用 Tasklets759.3.2 jiffies的回绕……12063. 3 ksoftirgd93.3用户空间和Hz121634老的BH机制…7894硬时钟和定时器12264工作队列94.1实时时钟122641工作队列的实现942系统定时器…12264.2使用工作队列829.5时钟中断处理程序12264.3老的任务队列机制…8596实际时间1246.5下半部机制的选择859.7定时器12666在下半部之间加锁…869.71使用定时器…126第7章内核同步介绍89972定时器竞争条件1287.1临界区和竞争条件8997.3实现定时器∴1287.2加锁9.8延迟执行中专非号·着中非省。鲁…l287.2.1到底是什么造成了并发执行9.8.1忙等待1297.22需要保护什么9.8.2短延迟l3073死锁93第10章内存管理…13374争用和扩展性9510.1页……1337.5小结…9610.2区……134XVI10.3获得页∴∴}3613.1.3 mm struct与内核线程…18810.3.1获得填充为0的页………………13713.2内存区域…18810.3.2释放页13713.2.1ⅥMA标志l89104slab层14313.2.2VM操作∴……19010.5slab分配器的接囗………1453.23内存区域的树型结构和内存10.6在栈上的静态分配748区域的链表结构9110.7高端内存的映射14813.24实际使用中的内存区域197107.1永久映射l4913.3操作内存区域19310.7.2临时映射…·14913.3.1 find_ vma19310.8分配函数的选择5013.3.2 find vma_prev(……193第11章虚拟文件系统75113.3.3find_vma_ Intersection()………l9411.1通用文件系统接口垂垂15l134mmap(和 do_mmap(O):创建地址11.2文件系统抽象层…15l间/9511.3Unix文件系统15213.5 mumma(和 do_ mumma(:删114VFS对象及其数据结构53除地址区间19611.5超级块对象13.6页表…∴∴∴…97116索引节点对象157第14章页高速缓存和页回写11.7目录项对象16ll4.1页高速缓存199117.1日录项状态16214.2基树20211.7.2目录项缓存14.3缓冲区高速缓存20311.7.3目录项操作144 pdflush后台例程118文件对象144.1 bdflush和 kupdated……204119和文件系统相关的数据结构/68144.2避免拥塞的方法:使用多线程…2051110和进程相关的数据结构第15章调试…2071111 Linux中的文件系统……17115.1调度前需要准备什么207第12章块ⅣO层…!17315.2内核中的bug20712.1解剖一个块设备1735.2.1 pinto20812.2缓冲区和缓冲区头17415.2.2记录等级209123bio结构体17615.2.3记录缓冲区…124请求队列…17815.24 syslogd和 klogd210125Ⅳ/O调度程序……179152.5 printk(和内核开发时需要留意12.5.1IO调度程序的作·179的…2l01252 Linus电梯18015.3oops……2101253最终期限I/O调度程序18015.3.1 ksymoops………2121254预测IO调度程序18215.3.2 kallsyms笫13章进程地址空间l85154内核调试配置选项2l213.1内存描述符∴…∴…I8615.5引发bug并打卬信息23187156神奇的系统请求键…2/478815.7内核调试器的传奇214
下载地址
用户评论