标题：Linux内核设计的艺术
图书信息
  作者：新设计团队
出版社: 机械工业出版社; 第1版 (2011年6月20日) 
平装: 444页 
正文语种: 简体中文 
开本: 16 
ISBN: 9787111347446 
条形码: 9787111347446
内容简介
《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》内容简介：很早就有一个想法，做中国人自己的、有所突破、有所创新的操作系统、计算机语言及编译平台。我带领的“新设计团队”（主要由中国科学院研究生院已毕业的学生组成）在实际开发自己的操作系统的过程中，最先遇到的问题就是如何培养学生真正看懂Linux操作系统的源代码的能力。开源的Linux操作系统的源代码很容易找到，但很快就会发现，培养学生看懂Linux操作系统的源代码是一件非常非常困难的事。
操作系统的代码量通常都是非常庞大的，动辄几百万行，即使是浏览一遍也要很长时间。比庞大的代码量更让学习者绝望的是操作系统有着极其错综复杂的关系。看上去，代码的执行序时隐时现，很难抓住脉络。代码之间相互牵扯，相互勾连，几乎无法理出头绪。更谈不上理解代码背后的原理、意图和思想。
对于学生而言，选择从源代码的什么地方开始分析本身就是一个难题。通常，学生有两种选择：一种是从main函数，也就是从C语言代码的总入口开始，沿着源代码的调用路线一行一行地看下去，学生很快就会发现源代码的调用路线莫名其妙地断了，但直觉和常识告诉他操作系统肯定不会在这个地方停止，一定还在继续运行，但却不知道后续的代码在哪里，这种方法很快就走进了死胡同；另一种则是从某一模块入手，如文件系统，但这样会无形中切断操作系统源码之间复杂的关系，如文件系统与进程管理的关系，文件系统与内存管理的关系，等等。使学生孤立地去理解一个模块，往往只能记住一些名词和简单概念，难以真正理解操作系统的全貌。用学生的话讲，他们理解的操作系统变成了“文科”的操作系统。 
编辑推荐
《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》对操作系统内核的驾驭能力和深刻理解程度达到世界顶尖级水平，是一本能真正引导你深入理解Linux内核设计思想的经典著作。结合真实的源码、349幅内核运行时序图和详细的文字描述，以一种开创性的方式对Linux内核进行了极为直观和透彻地阐述，读者可通过阅读本书提出自己的设计思想。 
作者简介
新设计团队始于世纪之交，不断发展、优胜劣汰、适者生存、自然形成。
团队始终不自量力地奉行高举高打的策略，只对计算机领域中基础的、有体系的事情感兴趣，且只做自己感兴趣的事。
团队不相信二流水平、三流心态，能作出世界顶级的工作。团队相信成功的决定因素是人，而不是物。
团队对艺术、对鉴赏力、对欣赏品味、对一切美好的事物都有着近乎狂热的追求。认为科学、技术的最高境界是艺术，认为世界的本源是通的。
团队崇尚理论体系、崇尚个性鲜明、崇尚独立思考。“没体系”是团队成员之间善意贬损的常用语，也是判断一件事是否值得关注的标准之一。
团队鄙视抄袭、弄虚作假。对别人热炒、做熟的事情不感兴趣，更不喜欢在别人的体系上狗尾续貂、移花接木，粉饰为“自主创新”。
团队强调理论，注重实践，讲究科学的研究方法，不屈膝权威，不迷信盲从。提出基础假设，构建逻辑自洽的体系，证伪、修正、再证伪、再修正，不断推进体系的完善。
团队钻研学术，但决不死板，学术和商业结合，彼此互为推进，最终改变整个时代的商业格局，是团队追求的目标。
团队特别注重诚信，提倡公平、公正。
团队内部是一方净土，既相互竞争，又相互帮助、相互协作。团队成员都在高高兴兴做自己喜欢的、感兴趣的事，没有时间顾及其他。勾心斗角、尔虞我诈、溜须拍马、拉帮结派……，在团队内部没有市场。
团队在上述思想的指导下，研发了基于图形、图像（而非基于字符、语句）的图示化程序设计集成开发环境，已成功的移植了linux 0.11，正确编译，正确boot，正确运行。现在正在研发新的操作系统，已初步实现了与现有的基于块概念的文件系统有较大差异的新的文件系统，据我们测试，相对于基于块设备的文件系统，在文件的读写速度上有较大优势。《Linux内核设计的艺术》一书，体现了我们设计新操作系统的过程中，对操作系统的理解。可能在不久的将来，我们也将我们在设计图示化程序设计平台中，对编译原理的理解，奉献给广大读者。 
目录
本书导读
前言
第1章　从开机加电到执行main函数之前的过程1
1.1　启动BIOS，准备实模式下的中断向量表和中断服务程序1
1.1.1　BIOS的启动原理2
1.1.2　BIOS在内存中加载中断向量表和中断服务程序3
1.2　加载操作系统内核程序并为保护模式做准备4
1.2.1　加载第一部分代码—引导程序（bootsect）5
1.2.2　加载第二部分代码—setup7
1.2.3　加载第三部分代码—system模块12
1.3　开始向32位模式转变，为main函数的调用做准备16
1.3.1　关中断并将system移动到内存地址起始位置0x0000016
1.3.2　设置中断描述符表和全局描述符表18
1.3.3　打开A20，实现32位寻址20
1.3.4　为在保护模式下执行head.s做准备21
1.3.5　head.s开始执行24
1.4　本章小结41
第2章　从main到怠速42
2.1　开中断之前的准备工作43
2.1.1　复制根设备号和硬盘参数表 44
2.1.2　物理内存规划格局45
2.1.3　虚拟盘设置与初始化46
2.1.4　内存管理结构mem_map初始化47
2.1.5　异常处理类中断服务程序挂接48
2.1.6　初始化块设备请求项结构50
2.1.7　与建立人机交互界面相关的外设的中断服务程序挂接52
2.1.8　开机启动时间设置55
2.1.9　系统开始激活进程056
2.1.10　进程相关事务初始化设置57
2.1.11　时钟中断设置59
2.1.12　系统调用服务程序挂接59
2.1.13　初始化缓冲区管理结构61
2.1.14　初始化硬盘63
2.1.15　初始化软盘65
2.1.16　开中断66
2.2　进程创建的最基本动作67
2.2.1　操作系统为进程0创建进程1做准备67
2.2.2　在进程槽中为进程1 申请一个空闲位置并获取进程号71
2.2.3　复制进程信息之前，先将一些数据压栈73
2.2.4　初步设置进程1管理结构74
2.2.5　进程0创建进程1的过程中发生时钟中断76
2.2.6　从时钟中断返回78
2.2.7　调整进程1管理结构79
2.2.8　设置进程1的线性地址空间及物理页面81
2.2.9　继续调整进程1管理结构84
2.2.10　操作系统如何区分进程0和进程187
2.2.11　进程0准备切换到进程189
2.2.12　系统切换到进程1执行90
2.3　加载根文件系统92
2.3.1　进程1如何开始执行96
2.3.2　进程1开始执行98
2.3.3　进程1开始以数据块的形式操作硬盘99
2.3.4　将找到的缓冲块与请求项挂接101
2.3.5　将请求项与硬盘处理函数挂接104
2.3.6　进行硬盘读盘前的准备工作105
2.3.7　给硬盘下达读盘指令106
2.3.8　进程1由于等待读盘操作挂起107
2.3.9　系统切换到进程0执行109
2.3.10　进程0的执行过程110
2.3.11　进程0执行过程中发生硬盘中断111
2.3.12　硬盘中断服务程序响应后，进程0继续执行113
2.3.13　再次响应硬盘中断并唤醒进程1114
2.3.14　读盘操作完成后，进程1继续执行116
2.3.15　进程1继续设置硬盘管理结构117
2.3.16　进程1获取软盘超级块，为加载根文件系统做准备118
2.3.17　进程1备份超级块数据119
2.3.18　进程1将根文件系统从软盘拷贝到虚拟盘120
2.3.19　进程1开始加载根文件系统122
2.3.20　进程1准备加载根文件系统超级块123
2.3.21　进程1加载根文件系统超级块124
2.3.22　进程1继续加载根文件系统126
2.3.23　进程1准备读取根目录i节点127
2.3.24　进程1加载根目录i节点128
2.3.25　进程1结束加载根文件系统的过程129
2.4　打开终端设备文件及复制文件句柄131
2.4.1　进程1与内核文件表挂接，为打开文件做准备133
2.4.2　确定打开操作的起点135
2.4.3　获得枝梢i节点—dev目录文件的i节点136
2.4.4　确定dev目录文件i节点为枝梢i节点137
2.4.5　继续返回枝梢i节点138
2.4.6　查找tty0文件的i节点138
2.4.7　将tty0设备文件的i节点返回给sys_open系统调用 139
2.4.8　分析tty0文件i节点140
2.4.9　设置文件管理结构并返回给用户进程141
2.4.10　进程1复制tty0文件句柄142
2.4.11　进程1继续复制tty0文件句柄144
2.5　创建进程2145
2.5.1　进程1准备创建进程2145
2.5.2　复制进程2管理结构并进行调整146
2.5.3　设置进程2的页目录项并复制进程2的页表146
2.5.4　调整进程2管理结构中与文件有关的内容146
2.5.5　进程1执行过程中发生时钟中断148
2.5.6　进程1从时钟中断返回，准备切换到进程2150
2.6　进程1等待进程2退出150
2.6.1　进程1查找它自己的子进程151
2.6.2　对进程2的状态进行处理151
2.6.3　切换到进程2执行153
2.7　shell程序的加载154
2.7.1　进程2开始执行156
2.7.2　为打开/etc/rc文件做准备156
2.7.3　进程2打开“/etc/rc”配置文件157
2.7.4　通过压栈为加载shell文件做准备158
2.7.5　为参数和环境变量设置做准备159
2.7.6　得到shell文件的i节点160
2.7.7　为加载参数和环境变量做准备161
2.7.8　根据i节点，对shell文件进行检测162
2.7.9　检测shell文件头163
2.7.10　备份文件头并进行分析163
2.7.11　对shell文件进行进一步分析165
2.7.12　拷贝参数和环境变量166
2.7.13　调整进程2的管理结构167
2.7.14　继续调整进程2管理结构168
2.7.15　释放进程2继承的页面169
2.7.16　检测协处理器170
2.7.17　调整shell程序所在的线性空间地址171
2.7.18　为shell程序准备参数和环境变量172
2.7.19　继续调整进程2管理结构173
2.7.20　调整EIP，使其指向shell程序入口地址173
2.7.21　shell程序执行引发缺页中断175
2.7.22　缺页中断中shell程序加载前的检测175
2.7.23　为即将载入的内容申请页面177
2.7.24　将shell程序载入新获得的页面177
2.7.25　根据shell程序的情况，调整页面的内容178
2.7.26　将线性地址空间与程序所在的物理页面对应179
2.8　系统实现怠速180
2.8.1　shell进程准备创建update进程180
2.8.2　进程2开始执行/etc/rc文件181
2.8.3　准备加载update进程181
2.8.4　update进程的作用182
2.8.5　shell程序检测“/etc/rc”文件183
2.8.6　shell进程退出184
2.8.7　shell进程退出善后处理185
2.8.8　进程1清理shell进程管理结构187
2.8.9　系统开始重建shell190
2.8.10　shell进程为何不会再次退出192
2.9　小结194
第3章　安装文件系统195
3.1　获取硬盘设备号196
3.1.1　用户发出安装硬盘文件系统指令196
3.1.2　从分析路径开始，准备查找hd1设备的挂接点197
3.1.3　以根目录i节点为依托，得到dev目录文件的i节点197
3.1.4　从dev目录文件中找到代表hd1设备文件的目录项198
3.1.5　得到hd1设备文件的i节点号199
3.1.6　释放dev目录文件的相关内容200
3.1.7　得到hd1设备文件的i节点200
3.1.8　获得hd1设备的设备号200
3.1.9　释放hd1设备文件的i节点201
3.2　获取虚拟盘上的挂接点202
3.3　得到hd1设备文件的超级块202
3.3.1　准备读取hd1设备文件超级块203
3.3.2　为hd1设备文件的超级块找到存储位置203
3.3.3　初始化空闲超级块并加锁203
3.3.4　从硬盘获得hd1设备文件的超级块204
3.3.5　加载逻辑块位图和i节点位图205
3.4　将hd1设备文件与mnt目录文件的i节点挂接206
3.5　小结207
第4章　文件操作208
4.1　打开文件211
4.1.1　用户程序调用open库函数产生软中断212
4.1.2　建立用户进程与文件管理表的关系213
4.1.3　从硬盘上获取helloc.txt文件的i节点214
4.1.4　将helloc.txt文件与文件管理表相挂接226
4.2　读文件227
4.2.1　为按照用户要求读入文件做准备228
4.2.2　确定要读入的数据块的位置230
4.2.3　将指定的数据块从硬盘读入到高速缓冲块233
4.2.4　将数据拷贝到用户指定的内存234
4.3　新建文件237
4.3.1　查找路径“/mnt/user/hello.txt”238
4.3.2　为hello.txt文件新建一个i节点240
4.3.3　为hello.txt文件新建目录项242
4.3.4　完成hello.txt新建操作并返回给用户进程245
4.4　写文件246
4.4.1　文件写入前的准备工作248
4.4.2　确定hello.txt文件的写入位置249
4.4.3　为数据的写入申请缓冲块252
4.4.4　将指定的写入数据从用户数据区拷贝到缓冲块253
4.4.5　数据同步到硬盘的方法1255
4.4.6　将文件写入硬盘的情况2257
4.5　修改文件260
4.5.1　对文件的当前操作指针进行重定位261
4.5.2　对文件进行修改261
4.6　关闭文件263
4.6.1　当前进程与文件管理表“脱钩”264
4.6.2　将文件管理表中hello.txt对应的引用次数减1265
4.6.3　hello.txt文件与文件管理表“脱钩”266
4.7　删除文件268
4.7.1　系统准备删除hello.txt文件268
4.7.2　删除hello.txt文件在硬盘上对应的数据和i节点270
4.7.3　对hello.txt文件所在的user目录做处理275
4.8　本章小结275
第5章　用户进程与内存管理277
5.1　用户进程的创建277
5.1.1　为创建进程str1准备条件277
5.1.2　为str1进程管理结构找到存储空间279
5.1.3　复制str1进程管理结构281
5.1.4　确定str1进程在线性空间中的位置282
5.1.5　复制str1进程页表并设置其对应的页目录项283
5.1.6　调整str1进程中与文件相关的结构285
5.1.7　建立str1进程与全局描述符表GDT的关联286
5.1.8　将str1进程设为就绪态287
5.2　为用户进程str1的加载做准备288
5.2.1　为str1进程加载自身对应的程序做准备288
5.2.2　读取str1可执行文件的i节点并统计参数和环境变量289
5.2.3　读取str1可执行文件的文件头290
5.2.4　对str1可执行程序文件头进行分析291
5.2.5　拷贝str1可执行程序的参数和环境变量292
5.2.6　调整str1进程管理结构中可执行程序对应的i节点292
5.2.7　继续调整str1进程管理结构—文件和信号相关的字段293
5.2.8　释放str1进程的页表294
5.2.9　重新设置str1的程序代码段和数据段295
5.2.10　创建环境变量和参数指针表296
5.2.11　继续根据str1可执行程序情况调整str1进程管理结构297
5.2.12　设置str1可执行程序的栈指针和eip值297
5.3　对缺页中断的处理298
5.3.1　产生缺页中断并由操作系统响应298
5.3.2　为str1程序申请一个内存页面299
5.3.3　将str1程序加载到新分配的页面中300
5.3.4　检测是否需要对页面剩余空间清0300
5.3.5　将str1程序占用的物理内存地址与str1进程的线性地址空间对应301
5.3.6　不断通过缺页中断加载str1程序的全部内容301
5.3.7　str1程序需要压栈302
5.3.8　str1程序第一次调用foo程序压栈302
5.3.9　str1程序第二次压栈，产生缺页中断302
5.3.10　处理str1程序第二次压栈产生的缺页中断302
5.3.11　str1程序继续执行，反复压栈并产生缺页中断303
5.3.12　str1程序运行结束后清栈303
5.4　str1用户进程的退出305
5.4.1　str1进程准备退出305
5.4.2　释放str1程序所占页面305
5.4.3　解除str1程序与文件有关的内容并给父进程发信号306
5.4.4　str1程序退出后执行进程调度307
5.5　多个用户进程“同时”运行308
5.5.1　依次创建str1、str2和str3进程308
5.5.2　str1进程压栈的执行效果309
5.5.3　str1运行过程中产生时钟中断并切换到str2执行309
5.5.4　str2执行过程遇到时钟中断切换到str3执行310
5.5.5　三个程序执行一段时间后在主内存的分布格局311
5.6　进程的调度与切换311
5.6.1　str1刚被shell创建并处于就绪态311
5.6.2　shell进程将自己挂起,然后准备切换到str1执行311
5.6.3　准备切换到str1进程执行312
5.6.4　str1执行时发生时钟中断314
5.6.5　时钟中断递减str1运行的时间片315
5.6.6　str1执行一段时间后挂起，shell进程新建str2进程315
5.6.7　str2运行期间发生时钟中断316
5.6.8　系统切换到str1程序执行317
5.7　内核的分页318
5.7.1　为设置内核的页目录表和页表做准备—所占空间清0318
5.7.2　设置内核对应的页目录项和页表项的内容319
5.7.3　设置内核对应的全局描述符表GDT320
5.8　页写保护321
5.8.1　进程A和进程B共享页面321
5.8.2　进程A准备进行压栈操作322
5.8.3　进程A的压栈动作引发页写保护322
5.8.4　将进程A的页表指向新申请的页面323
5.8.5　拷贝原页面内容到进程A新申请的页面324
5.8.6　进程B准备操作共享页面325
5.8.7　假设进程B先执行压栈操作的情况325
5.9　小结326
第6章　多个进程“同时”操作一个文件327
6.1　三个进程操作同一个文件327
6.1.1　进程A执行，hello.txt文件被打开328
6.1.2　进程A读取hello.txt文件并由于等待硬盘中断而被系统挂起328
6.1.3　进程B准备打开hello.txt文件330
6.1.4　系统准备为进程B获取hello.txt文件的i节点332
6.1.5　系统找到hello.txt文件已经载入的i节点333
6.1.6　系统准备为进程B从硬盘上读取hello.txt文件334
6.1.7　系统找到了正在操作的缓冲块，将进程B挂起335
6.1.8　系统再次切换到进程0执行337
6.1.9　进程C启动并打开hello.txt文件337
6.1.10　进程C也由于等待缓冲块解锁而被系统挂起338
6.1.11　缓冲块解锁后先唤醒进程C339
6.1.12　系统将进程B设为就绪状态340
6.1.13　系统将指定数据写入缓冲块341
6.1.14　写入完成后，进程C继续执行341
6.1.15　进程C准备切换到进程B342
6.1.16　进程C切换到进程B执行，进程B唤醒进程A342
6.1.17　进程B不断执行，直到时间片减为0后切换到进程A执行343
6.1.18　进程A、B、C退出，写入数据由update进程同步344
6.2　缓冲区与外设的数据同步344
6.2.1　系统不断为进程A向缓冲区写入数据346
6.2.2　继续执行引发缓冲块数据需要同步346
6.2.3　将缓冲区中的数据同步到硬盘上347
6.2.4　进程A由于等待空闲请求项而被系统挂起349
6.2.5　进程B开始执行350
6.2.6　进程B也被挂起351
6.2.7　进程C开始执行并随后被挂起352
6.2.8　进程A和进程C均被唤醒352
6.2.9　进程B切换到进程A执行354
6.3　小结356
第7章　IPC问题358
7.1　管道机制358
7.1.1　为管道文件在文件管理表中申请空闲项360
7.1.2　为管道文件与进程建立联系创造条件360
7.1.3　创建管道文件i节点361
7.1.4　将管道文件i节点与文件管理表建立联系362
7.1.5　将管道文件句柄返回给用户进程363
7.1.6　读管道进程开始操作管道文件363
7.1.7　写管道进程向管道中写入数据364
7.1.8　写管道进程继续向管道写入数据366
7.1.9　写管道进程已将管道空间写满366
7.1.10　写管道进程挂起366
7.1.11　读管道进程从管道中读出数据367
7.1.12　读管道进程继续执行，不断从管道中读出数据369
7.1.13　读管道进程执行中发生时钟中断369
7.1.14　读管道进程执行过程中再次发生时钟中断370
7.1.15　读管道进程切换到写管道进程执行371
7.1.16　写管道进程挂起切换到读管道进程执行371
7.1.17　读管道进程继续执行，直到把管道中的数据读完372
7.1.18　读取完成后，读进程挂起，写进程继续执行373
7.2　信号机制374
7.2.1　processig进程开始执行376
7.2.2　processig进程进入可中断等待状态377
7.2.3　sendsig进程开始执行并向processig进程发信号379
7.2.4　系统检测当前进程接收到信号并准备处理381
7.2.5　系统检测信号处理函数指针挂接是否正常382
7.2.6　调整processig进程的内核栈结构，使之先执行信号处理函数383
7.2.7　信号对进程执行状态的影响386
7.3　小结393
第8章　操作系统的设计指导思想395
8.1　运行一个最简单的程序，看操作系统为程序运行做了哪些工作395
8.2　操作系统的设计指导思想—主奴机制398
8.2.1　主奴机制中的进程及进程创建机制399
8.2.2　操作系统在内存管理中的主奴机制400
8.2.3　操作系统在文件系统中体现的主奴机制401
8.3　实现主奴机制的三种关键技术402
8.3.1　保护和分页402
8.3.2　特权级405
8.3.3　中断405
8.4　建立主奴机制的决定性因素—先机407
8.5　软件和硬件的关系：主机与进程、外设与文件408
8.5.1　非用户进程—进程0、进程1、shell进程408
8.5.2　文件与数据存储409
8.6　父子进程共享页面414
8.7　操作系统的全局中断与进程的局部中断—信号414
8.8　小结415
结束语415
“新设计团队”简介416
附录　搭建Linux 0.11系统环境421