基本信息·出版社:电子工业出版社 ·页码:482 页 ·出版日期:2009年08月 ·ISBN:7121085151/9787121085154 ·条形码:9787121085154 ·版本:第1版 · ...
商家名称 |
信用等级 |
购买信息 |
订购本书 |
|
|
独辟蹊径品内核:Linux内核源代码导读 |
|
|
|
独辟蹊径品内核:Linux内核源代码导读 |
|
基本信息·出版社:电子工业出版社
·页码:482 页
·出版日期:2009年08月
·ISBN:7121085151/9787121085154
·条形码:9787121085154
·版本:第1版
·装帧:平装
·开本:16
·正文语种:中文
内容简介 《独辟蹊径品内核:Linux内核源代码导读》根据最新的2.6.24内核为基础。在讲述方式上,《独辟蹊径品内核:Linux内核源代码导读》注重实例分析,尽量在讨论“如何做”的基础上,深入讨论为什么要这么做,从而实现《独辟蹊径品内核:Linux内核源代码导读》的写作宗旨:“授人以渔”。在内容安排上,《独辟蹊径品内核:Linux内核源代码导读》包含以下章节x86硬件基础;基础知识;Linux内核Makefile分析;Linux内核启动;内存管理;中断和异常处理;系统调用;信号机制在类UNIX系统中;时钟机制;进程管理;调度器;文件系统;常用内核分析方法。
《独辟蹊径品内核:Linux内核源代码导读》适合初、中级Linux用户、从事内核相关开发的从业人员,也可以作为各类院校相关专业的教材及Linux培训班的教材,也可作为Linux内核学习的专业参考书。
编辑推荐 《独辟蹊径品内核:Linux内核源代码导读》由电子工业出版社出版。
目录 第1章 x86硬件基础1
1.1 保护模式1
1.1.1 分页机制1
1.1.2 分段机制7
1.2 系统门13
1.3 x86的寄存器14
1.4 典型的PC系统结构简介16
第2章 基础知识18
2.1 AT&T与Intel汇编语法比较18
2.2 gcc内嵌汇编20
2.3 同步与互斥25
2.3.1 原子操作25
2.3.2 信号量27
2.3.3 自旋锁29
2.3.4 RCU机制35
2.3.5 percpu变量39
2.4 内存屏障41
2.4.1 编译器引起的内存屏障41
2.4.2 缓存引起的内存屏障44
2.4.3 乱序执行引起的内存屏障47
2.5 高级语言的函数调用规范49
第3章 Linux内核Makefile分析52
3.1 Linux内核编译概述52
3.2 内核编译过程分析54
3.3 内核链接脚本分析62
第4章 Linux内核启动65
4.1 BIOS启动阶段65
4.2 实模式setup阶段67
4.3 保护模式startup_3277
4.4 内核启动start_kernel()84
4.5 内核启动时的参数传递90
4.5.1 内核参数处理91
4.5.2 模块参数处理95
第5章 内存管理99
5.1 内存地址空间99
5.1.1 物理内存地址空间99
5.1.2 虚拟地址空间101
5.2 内存管理的基本数据结构104
5.2.1 物理内存页面描述符104
5.2.2 内存管理区106
5.2.3 非一致性内存管理108
5.3 内存管理初始化109
5.3.1 bootmemalloctor的初始化109
5.3.2 页表初始化115
5.3.3 内存管理结构的初始化118
5.4 内存的分配与回收127
5.4.1 伙伴算法127
5.4.2 SLUB分配器138
第6章 中断与异常处理152
6.1 中断的分类152
6.2 中断的初始化156
6.2.1 异常初始化156
6.2.2 中断的初始化160
6.2.3 中断请求服务队列的初始化167
6.3 中断与异常处理171
6.3.1 特权转换与堆栈变化171
6.3.2 中断处理172
6.3.3 异常处理177
6.4 软件中断与延迟函数180
6.4.1 softirq180
6.4.2 tasklet185
6.5 中断与异常返回187
6.6 中断优先级回顾191
6.7 关于高级可编程中断控制器192
6.7.1 APIC初始化193
第7章 信号机制199
7.1 信号机制的管理结构200
7.2 信号发送204
7.3 信号处理210
第8章 系统调用220
8.1 Libc和系统调用220
第9章 时钟机制226
9.1 clocksource对象227
9.1.1 clocksource概述227
9.1.2 clocksource初始化228
9.2 tickless机制232
9.2.1 tickless由来232
9.2.2 clockeventdevice对象概述234
9.2.3 clockeventdevice对象的初始化236
9.3 High-ResolutionTimers247
9.3.1 High-ResolutionTimers管理结构247
9.3.2 High-ResolutionTimers初始化252
9.3.3 High-ResolutionTimers操作258
9.4 时钟中断处理268
9.4.1 时钟维护276
9.4.2 进程时间信息统计281
9.5 软件定时器283
9.5.1 基本管理结构283
9.5.2 初始化284
9.5.3 注册与过期处理287
第10章 进程管理295
10.1 进程描述符296
10.1.1 进程状态297
10.1.2 进程标识299
10.1.3 进程的亲缘关系300
10.1.4 进程的内核态堆栈301
10.1.5 进程的虚拟内存布局302
10.1.6 进程的文件信息305
10.2 进程的建立306
10.2.1 建立子进程的task_struct对象308
10.2.2 子进程的内存区域315
10.2.3 子进程的内核态堆栈323
10.2.4 0号进程的建立325
10.3 进程切换327
10.4 进程的退出331
10.4.1 do_exit函数331
10.4.2 task_struct结构的删除334
10.4.3 通知父进程335
10.5 do_wait()函数338
10.6 程序的加载344
第11章 调度器351
11.1 早期的调度器351
11.2 CFS调度器的虚拟时钟353
11.3 CFS调度器的基本管理结构357
11.4 CFS调度器对象359
11.5 CFS调度操作360
11.5.1 update_curr()函数360
11.5.2 scheduler_tick()函数362
11.5.3 put_prev_task_fair()函数364
11.5.4 pick_next_task()函数366
11.5.5 等待和唤醒操作368
11.5.6 nice系统调用373
第12章 文件系统376
12.1 Ext2的磁盘结构376
12.2 Ext2的内存结构385
12.3 虚拟文件系统的管理结构387
12.3.1 文件系统对象388
12.3.2 VFS的超级块389
12.3.3 VFS的inode结构400
12.3.4 VFS的文件对象406
12.3.5 VFS的目录对象409
12.3.6 VFS在进程中的文件结构412
12.4 文件系统的挂载413
12.5 路径定位425
12.6 文件打开与关闭441
12.7 文件读写449
12.7.1 缓冲区管理449
12.7.2 文件读写操作分析456
第13章 常用内核分析方法471
13.1 准确定位同名宏及结构体471
13.2 准确定位同名函数473
13.3 利用linkmap文件定位全局变量474
13.4 准确定位函数调用线索476
13.5 SystemTap在代码分析中的使用479
……
序言 几乎每一个操作系统内核的学习者在初学阶段都会感觉到难以入门。这是由于内核涉及到知识面非常广泛,需要学习者从根本上掌握大量的知识,这包括:程序编译,链接,装载的细节,操作系统理论,计算机系统体系结构,数据结构与算法,深厚的C/汇编语言编程功底。如此相对较高的门槛常常令很大一部分初学者望而却步。那么是不是一定要先学好以上的各门知识后才能学习内核呢?事实上大部分学习者在学习以上各门知识都会遇到同样的问题,因为知识是一个网状结构。所以重要的不是先去学会什么知识,而是学会如何学习,学会在自己掌握的知识体系上提出问题,学会思考,进而坚持不懈的解决心中的疑问。笔者从学完C/C++ 语言开始,由于C/C++ 的示例程序都是在命令行下的,于是常常想如何才能编写出视窗程序,学习了MFC,但是同样想不通诸如WM_CHAR,WM_LBUTTONDOWN 的消息从何而来,带着MFC 中诸多疑问,笔者开始学习Windows SDK 程序开发,在这个学习过程中感觉对MFC 的认识更加深入了,但同时又有新的问题想不通,于是进而学习Windows DDK,之后开始学习操作系统内核。在这个过程中,笔者也遇到过数不尽的疑问,但是都是需要的时候再补充相关知识。因此初学者要明白,学习并不需要等到“万事具备”了才可以开始。需要的是保持好奇心,养成思考的习惯,树立解决问题的决心。很多读者渴望寻找好的入门教材,也常常有人问看什么书才能进步的快,但是当他们看了别人推荐的书却没有取得同样的收获,这是为什么呢?笔者认为,读书有以下几种境界:
1. 面对书上讲到的某个知识点,不能接合自己掌握的知识提出疑问,仅仅知识死记书本上的东西。这种状态就算学到最高境界,也仅仅只是能把书本上的知识点完好的记下来在脑海中形成孤立的知识节点。
2. 面对书本上讲到的某个知识点,能接合自己掌握的知识提出疑问,但是大多数时候没有探索精神,仅仅局限于到其他书籍或者请教别人来排除心中的疑问。脑海中的知识形成了简单网状结构,但由于探索能力长期得不到锻炼,综合自己的知识去分析和解决问题的能力十分有限。
3. 面对书上讲到的某个知识点,能接合自己掌握的知识提出疑问,并且能根据问题补充相关必要的知识,不断综合分析各知识点的关系,提出各种假设和验证排除的方法并亲自验证,解决不了问题决不罢休。如能经过长期锻炼,其脑海中的知识点形成复杂的网状结构,综合分析能力必将加强。
4. 根据自己掌握的知识,提出全新的问题,并始终坚持找到答案为止。这种境界需要渊博的知识作为基础。
因此,不要还没学内核就被吓倒,说了这么多看似和内核无关的东西,就是要从先排除读者的心理担忧,树立正确的态度,重要的不是学会什么,而是学会学习。确定自己处于哪一种学习境界,然后通过学习某项具体的知识把自己提升到更高的境界。在现实生活中我们不难发现,能力强的学什么都又快又好。其根本原因在于他们处于更高的学习境界,并形成了良性循环!
有很多的人都渴望学习操作系统内核,但是内核涉及到的知识非常广泛,因此很多人半途而废,许多人往往抱怨没有好的书籍,教材。实际上,对于同一本书籍,不同的读者收获也是不同的,这取决于他们的态度和学习方法。笔者建议,在读书的时候,一定要以自己心中的疑问作为主线,而不要没有任何疑问就死记书本上的知识。
如何使用本书
笔者认为对于任何知识的学习,首先是以自我为中心,任何书籍资料都是用来解答读者心中的疑问的,因此在你阅读一本书时,首先要明确自己的疑问是什么?这可以是一个非常梗概的问题,例如:“Linux 内核是什么?”;也可以是一个非常细节的问题,例如:“按下键盘上的A,到屏幕上显示出字符A 的内部原理”。当你有了来自内心深处经过独立思考的疑问后,阅读对你来说是一种享受,一种乐趣。来自内心的疑问,经过不断的综合分析,缜密的推理,坚持不懈的查阅和求索,之后拨开迷雾见天日喜悦只有经过才能体会。虽然本书是一本很厚的书,但是这不是畏惧的理由,也不要因为它厚,就给自己下一个决心,制定一个阅读计划,几个月要读完本书。学习是主动探求的过程,而不是被动接受,在这个过程中,有太多的东西,不是谁可以计划出来的。例如:在笔者学习内核之初,看到大量的传言,读完《Understanding the linux Kernel》,读完《Linux 内核情景分析》... 就可以成为“高手”了。于是笔者常常捧着厚厚的书,寻思着自己什么时候可以读完,然而有时好几天也前进不了几页,免不了感慨自己今生将与“高手”无缘,但是又心有不甘,于是囫囵吞枣的“快速”前进,但是越前进,就越感觉到艰难。“欲速则不达”这个道理人人都懂,但是在切身体会之前,人人都会犯这个错误。在经历了很长一段曲折和郁闷之后,笔者摆脱了“书”的束缚,完全以自己的疑问为中心,例如在读到中断处理时,由于知识不够全面,于是丢开内核的书籍,阅读了大量的计算机体系结构方面的资料,同样计算机体系结构的书籍也很厚,但是我也没有想过要把它们读完,这时只捡中断相关的读,之后再来读内核的书籍,发现自己原理懂了,但是具体到理解代码时,就迷糊了,于是有补充GCC 内嵌汇编,C 代码编译到汇编代码的相关知识,反复试验等等。这个过程很慢,但是积累到最后,笔者发现自己读的非常快,甚至可以不读了,因为很多地方,只要读到前面的,就领悟了作者后面想要说什么了。
至今,我仍然没有完成当初为了成为“高手”而制定下的“宏伟”目标,因为我没有完整的读完《Understanding the Linux Kernel》、《Linux 内核情景分析》或《Linux 内核完全剖析》等等这类传说中“惊世骇俗”之作中的任何一本。但是笔者却从这些著作中受益菲浅。
现在,你应该知道要如何使用本书了吧?那就是不要拘泥如任何教条。虽然本书经笔者从初学到现在的心得体会以及相关笔记和资料整理而成,初学者的大量疑问都能在本书本书中找到答案。但是每个人都是独一无二的,笔者希望任何一个读者能综合利用本书和其它相关资料寻找你自己的答案。多问一点为什么,多一点假设,多一点思考,多一点推理,多一点试验,多一点坚持。最后,你会感慨原来传说中的任何“秘籍”都是“浪得虚名”,因为读完它,你不一定能成为“高手”,而“高手”却不需要读完它。能否成为“高手”的决定性因素取决于你的学习方法和学习态度,而好的“秘籍”仅仅只是催化剂。
由于笔者水平有限,纰漏之处在所难免,因此希望读者能够指正。笔者的联系方式是:
Addylee2004@163.com. 另外对本书有任何问题,意见或建议,勘误等等,欢迎前来http://
www.osplay.org与笔者进行讨论。
文摘 插图:
在上面这个例子中inetfreeifa并没有执行真正的释放操作,它调用call-rcul()注册了一个回调函数inetrcufreeifa(),将来这个回调函数来执行真正的释放操作。
另外内核中还有大量的:RC[了的相关函数,在明白RCIJ机制之后,这些代码都很容易理解,在此不再——列举。2.3.5percpu变量
相对于自旋锁来说,RCU减小了临界区同步的开销,但是并不是所有应用都满足RCU的前提条件。例如在CPU的调度队列中,假设多个CPU共享同一个调度队列,各个CPU需要频繁对调度队列中的关键数据结构进行操作,而且读操作次数并不会远远小于写操作次数。因此必须使用自旋锁来保护。事实上内核中进程切换非常频繁,各个CP[了都需要频繁地访问调度队列。在这种情况下,某些CPU由于获取不到自旋锁进入忙等待状态。为了提高性能,最好的办法就是各个CPU使用各自的运行队列,这样在访问时就不需要使用锁来保护,当某个CPU的就绪进程个数为O或大于某个阈值时,启动负载均衡机制来平衡各个CPU的运行队列。我们把这样的变量称为percpu变量。
通常在程序中定义的全局变量,编译后这些变量位于执行文件的数据区,可执行文件加载之后,这些变量被复制到对应的内存中,源程序中的变量名用于对变量进行寻址。而percpu变量的关键就是:要求根据CPU的个数,在内存中生成多份拷贝,并且能够根据变量名和CPU编号,正确地对各个CPU的变量进行寻址。可以通过下面的方法来定义一个percpu变量。