<<Linux内核源代码情景分析》一书

<<Linux内核源代码情景分析》一书

书名:Linux内核源代码情景分析

内 容 提 要
本书采取类似于英语教学中行之有效的情景会话的教学方法,全面深入地剖析了Linux最新版本(2.4.0)核心源代码,并对Linux核心的独特优点和需要进一步改进的问题作了精辟的评述。
全书分上下两册。上册包括预备知识、存储管理、中断和系统调用、进程和进程调度、传统的Unix进程间通讯以及文件系统共六章,下册则分基于Socket的进程间通讯、设备驱动、多处理器SMP系统结构以及系统引导和初始化四章。上下两册不可分割,是一个有机的整体。
本书写法独特,论述精辟,不回避代码分析中的难点,可以作为操作系统高级课程的教材,也可以作为计算机软件专业和其他相关专业大学本科高年级学生和研究生深入学习操作系统以至软件核心技术的重要参考书。同时,还可作为各行业从事软件开发的工程师、研究人员以及其他对Linux最新技术感兴趣者的自学教材。

第1章 预备知识 1
1.1 Linux内核简介 1
1.2 Intel X86 CPU系列的寻址方式 6
1.3 i386的页式内存管理机制 12
1.4 Linux内核源代码中的C语言代码 15
1.5 Linux内核源代码中的汇编语言代码 21
第2章 存储管理 29
2.1 Linux内存管理的基本框架 29
2.2 地址映射的全过程 33
2.3 几个重要的数据结构和函数 40
2.4 越界访问 53
2.5 用户堆栈的扩展 57
2.6 物理页面的使用和周转 66
2.7 物理页面的分配 77
2.8 页面的定期换出 90
2.9 页面的换入 125
2.10 内核缓冲区的管理 131
2.11 外部设备存储空间的地址映射 154
2.12 系统调用brk( ) 160
2.13 系统调用mmap( ) 178
第3章 中断、异常和系统调用 191
3.1 X86 CPU对中断的硬件支持 192
3.2 中断向量表IDT的初始化 196
3.3 中断请求队列的初始化 203
3.4 中断的响应和服务 209
3.5 软中断与Bottom Half 221
3.6 页面异常的进入和返回 233
3.7 时钟中断 236
3.8 系统调用 244
3.9 系统调用号与跳转表 256



第4章 进程与进程调度 263
4.1 进程四要素 263
4.2 进程三部曲:创建、执行与消亡 276
4.3 系统调用fork( )、vfork( )与clone( ) 280
4.4 系统调用execve( ) 305
4.5 系统调用exit( )与wait4( ) 337
4.6 进程的调度与切换 356
4.7 强制性调度 377
4.8 系统调用nanosleep( )和pause( ) 384
4.9 内核中的互斥操作 398
第5章 文件系统 415
5.1 概述 415
5.2 从路径名到目标节点 431
5.3 访问权限与文件安全性 469
5.4 文件系统的安装和拆卸 491
5.5 文件的打开与关闭 540
5.6 文件的写与读 579
5.7 其他文件操作 640
5.8 特殊文件系统 /proc 653
第6章 传统的Unix进程间通信 687
6.1 概述 687
6.2 管道和系统调用pipe( ) 689
6.3 命名管道 709
6.4 信号 716
6.5 系统调用ptrace( )和进程跟踪 756
6.6 报文传递 773
6.7 共享内存 802
6.8 信号量 829

第7章 基于socket的进程间通信 1
7.1 系统调用socket( ) 1
7.2 函数sys_socket( )──创建插口 10
7.3 函数sys_bind( )──指定插口地址 25
7.4 函数sys_listen( )──设定server插口 35
7.5 函数sys_accept( )──接受连接请求 37
7.6 函数sys_connect( )──请求连接 48
7.7 报文的接收与发送 65
7.8 插口的关闭 102
7.9 其他 117
第8章 设备驱动 119
8.1 概述 119
8.2 系统调用mknod( ) 127
8.3 可安装模块 134
8.4 PCI总线 178
8.5 块设备的驱动 248
8.6 字符设备驱动概述 326
8.7 终端设备与汉字信息处理 330
8.8 控制台的驱动 362
8.9 通用串行外部总线USB 413
8.10 系统调用select( )以及异步输入/输出 570
8.11 设备文件系统devfs 589
第9章 多处理器SMP系统结构 607
9.1 概述 607
9.2 SMP结构中的互斥问题 611
9.3 高速缓存与内存的一致性 615
9.4 SMP结构中的中断机制 623
9.5 SMP结构中的进程调度 636
9.6 SMP系统的引导 642



第10章 系统引导和初始化 663
10.1 系统引导过程概述 663
10.2 系统初始化(第一阶段) 667
10.3 系统初始化(第二阶段) 683
10.4 系统初始化(第三阶段) 719
10.5 系统的关闭和重引导 737
      
前 言

本书着重于对Linux系统最新版本(2.4.0)内核源代码进行情景描述和情景分析。
什么是情景描述?什么是情景分析?
不妨以英语的教学为例。大家都知道,有一种很有效的方法是通过“情景会话”学习英语。例如,去剧院问路要说些什么,去图书馆借书要说些什么,去餐馆吃饭碰上了熟人又说些什么,等等。每一个这样的“情景”都是一个常见或常用的会话过程。以这样的一些情景为线索,沿着这些线索讲解“这是被动语态”、“那是习惯用法”,就容易引起学习人的兴趣从而印象深刻,并且每学了这样一个情景就能够实际运用。另外,由于来自现实生活的情景在语法、语义等方面都不是单一的,在学习一个情景的时候通常都会涉及该语言种种不同的方面,通过一系列精心安排的情景会话的学习,就能对英语逐步地建立起比较全面的认识。事实上,就英语的学习而言,纯粹的系统化学习方法几乎是不现实的。事实上,很少有人通过读字典来学单词,而都是结合课文来学,每篇课文实际上也是一个情景。当然,系统化的学习还是要的,学了情景对话以后还要再系统地学习语法。但是无可否认的是,从情景对话入手学习英语比从语法入手要有效得多。相信读者会有这方面的体会和经历。
现在来看对Linux内核的学习。如果以若干经过精心安排的情景为线索,例如,打开一个文件的全过程,执行一个可执行程序的全过程,从一个进程发送一个报文到另一个进程的过程等等,结合内核源代码逐个加以讲解,并且在讲解过程中有针对性地介绍所涉及的数据结构和算法,读者就能得到对整个内核的生动而深刻的理解。本书的宗旨之一就在于引导读者走过许多这样的“情景”,从而建立起对Linux内核的全面的认识。至于情景的安排,仍然按照操作系统的原理分成若干章,例如存储管理、进程管理、文件系统等等。在每一章中,除了必要的叙述以外,都挑选了若干重要的情景,结合源代码逐个加以讲解。
本书所用的源代码,刚开始编写初稿时取自当时最新的Linux内核2.3.38版,后来历经2.3.98和2.4.0测试版,最后依据2.4.0正式版重新修改定稿。读者可以在相关的网站上自行下载该版内核的全部源代码。可以肯定,当读者看到本书时,甚至本书付印时,最新的版本已不再是2.4.0了。但是不管怎样我们总得要锁定一个版本,这就是2.4.0。
一般情况下,分析操作系统源代码的专著或教材习惯上都是这样安排的:以主要数据结构的定义为核心,以数据结构之间的联系为线索,内容则以对文件、模块和函数的功能描述为主,辅以若干函数中的代码片断作为实例,以达到介绍、分析各种特定机制的目的。这种思路和安排基本上类似于先讲语法规则后举一些例句的外语教学方法,它比较适合于只要求对内核和它的原理有粗略了解的读者,但对需要深入理解内核或实际从事这方面工作的读者就未必合适。其实,这种安排对于初学者也未必是最好的。不错,要理解一个操作系统的内在机制及其实现机理,当然需要了解主要数据结构的组成,了解数据结构之间的联系,了解整个内核代码的模块划分、文件划分和功能分解,了解主要函数对有关数据结构操作的大致逻辑流程。问题在于,怎样才能使读者和学生达到这些要求。根据我们多年来的切身体会,我们决定从具体、鲜活的源代码入手作情景分析,在分析过程中逐步引入相关的数据结构和互相间的联系,介绍具体函数的逻辑流程及其物理背景乃至代码作者的某些高超技巧,让读者和作者一起完成必要的抽象过程,通过读者的思索,最后达到深入而全面的理解。
对于从事系统设计或实现的读者,源代码的阅读和理解是一项重要的基本功。写小说的人大多是读了许多名著和文学评论以后,而不是读了“小说概论”以后才学到写作技巧,进而写出受读者喜爱的作品。写程序的人又何尝不是如此。本书的目的之一就是为读者提供一些类似于文学评论的材料。另一方面,源代码的阅读和理解也是必要的。在某种意义上,源代码本身既是最准确的说明书也是最权威的教科书,因为由它所构成的系统切切实实在运行。我们自己就有过这样的经历:学了一些原理和抽象的流程就自以为懂了,可是拿源代码一看却怎么也对不上号。于是下决心钻进去,花了九牛二虎之力才搞懂。Linux内核源代码还为计算机行业的工作人员树立了一个参照物。我们在工作中常常看到,人们(包括我们自己)在碰到问题时往往会先想一想:这在Linux(以前是Unix)里面是怎样实现的?或者在Linux环境中能否实现?再查看一下有关的源代码,便有了主张。有时甚至就在源代码中找几个文件加以裁剪、修改,问题很快就解决了(但须遵守GPL中的有关规定)。诚然,Linux内核源代码的阅读和理解是个艰苦的过程,最好能有些指导,有些帮助,而这正是我们写作本书的目的。
希望读者在每读完一章后能做两个小结。一个是关于数据结构组成和数据结构之间联系的小结,另一个是关于执行过程以及函数调用关系的小结。读者为了完成这两个小结,可能不得不回过头去再读一遍甚至几遍前面的内容。从内容的选定和编排的角度来说,最理想的当然是严格遵循“先说明后引用”的原则,像平面几何那样建立起一个演绎体系。可是,对于一个实际的系统,特别是对于它的源代码,这种完全线性的叙述和认识过程是不现实的。实际的认识过程是螺旋式的,这也决定了常常需要反复读几遍才能理解。所以,对于一个操作系统的源代码,读到后面再返回前面,再读到后面又返回前面,这几乎是必然的过程。真有决心深入了解Linux内核的读者应该有这个思想准备。我们相信,读者在读完全书以后,如果闭目细想,一定会有一种在一个新到的城市中由向导陪同走街串巷,到过了大量的重要景点,最后到了某个高楼之顶的旋转餐厅鸟瞰整个城市时常会有的那种心情。
由于篇幅的原因,全书分上下两册。上册包括预备知识、存储管理、中断和系统调用、进程和进程调度、文件系统以及传统的Unix进程间通讯,共六章。下册则分基于socket的进程间通讯、设备驱动、多处理器SMP系统结构以及系统引导和初始化,共四章。上下两册不可分割,是一个有机的整体。
本书的题材决定了读者主要是中、高级的计算机专业人员,以及大学有关专业的高年级学生和研究生。但是,我们在写作中也尽量照顾到了非计算机专业的学生和初学者(因此程度高的读者有时候也许会觉得书中有些讲解过于?嗦)。一般而言,读者只要有一些操作系统和计算机系统结构方面的基础知识,并粗通C语言,就可以阅读本书。
就像软件免不了有错一样,对软件的理解和诠释也一定会有错误,人们能做的只是尽量减少错误。我们可以负责地说,本书付印前在文字中已经没有我们知道而没有改正的错误,更没有故意误导读者的内容。但是,我们深知错误一定是有的,我们欢迎讨论,欢迎批评。
20年前,本书的两位作者从不同单位调入浙江大学计算机系,共事期间曾共同承担过若干计算机应用项目的开发、研究。后来第一作者去了美国,目前在美定居,继续从事计算机专业的工作;第二作者已从学校退休,目前受聘在杭州恒生电子股份有限公司任职。出于难忘的友情和其他一些难以割舍的情结(包括对Unix和Linux的共同爱好),两年前通过越洋电话商定要合作写几本有关Linux的书,此刻在读者手上的就是其中的第一本,其余的就要看条件是否允许了。
从成书到出版,曾得到了陈大中、曾抗生、金通? 、俞瑞钊几位教授和其他许多国内朋友的鼓励和支持,作者感谢他们。特别要提到的是,恩师何志钧教授在过去和现在都给了作者许多的关心和帮助,令作者终生难忘,本书的出版在某种意义上也是对恩师的一次汇报,同时表示由衷的感谢。
作者还要感谢恒生电子股份有限公司黄大成总裁、彭政纲董事长以及其他领导人对作者,特别是第二作者开展Linux研究的支持。他们为本书第二作者提供了很好的工作条件,使其在工作之余继Unix之后还能再从事Linux技术的研究。作为全国著名软件企业的决策者,他们对软件核心技术的敏锐眼光以及采用最新技术为我国金融证券行业开发全新的大型应用软件的战略决策,令人钦佩。感谢他们,祝愿他们取得更大的成功。
最后,还要感谢谢敏、王红女、章西、李清瑜几位小姐,她们在承担公司繁重工作的同时利用业余时间为本书文稿的录入和整理付出了大量的辛勤劳动。
本书的出版,像任何其他技术专著一样,除了错误之外总还会有许多不尽人意的地方,欢迎国内外的专家和本书读者给我们指出,以便改进。

毛德操 (Decao Mao)
19 Orchard Hill Road,
Newtown, CT 06470
USA

胡希明
杭州恒生电子股份有限公司
杭州市解放路138号纺织大厦11F (310009)

2001年5月1日