Linux内核完全注释 内核版本 0.11(0.95) 修正版 V1.9.5 赵 炯 著 www.oldlinux.org [email protected] Linux 内核 0.11 完全注释 A Heavily Commented Linux Kernel Source Code Linux Version 0.11 修正版 1.9.5 (Revision 1.9.5) 赵炯 Zhao Jiong [email protected] www.plinux.org www.oldlinux.org 2004-05-21 内容简介 本书对 Linux 早期操作系统内核(v0.11)全部代码文件进行了详细全面的注释和说明,旨在使读者能够在尽量短的时间 内对Linux的工作机理获得全面而深刻的理解,为进一步学习和研究Linux系统打下坚实的基础。虽然所选择的版本较低, 但该内核已能够正常编译运行,其中已经包括了LINUX工作原理的精髓,通过阅读其源代码能快速地完全理解内核的运作 机制。书中首先以Linux源代码版本的变迁历史为主线,详细介绍了Linux系统的发展历史,着重说明了各个内核版本之间 的重要区别和改进方面,给出了选择 0.11(0.95)版作为研究的对象的原因。另外介绍了内核源代码的组织结构及相互关系, 同时还说明了编译和运行该版本内核的方法。然后本书依据内核源代码的组织结构对所有内核程序和文件进行了注释和详细 说明。每章的安排基本上分为具体研究对象的概述、每个文件的功能介绍、代码内注释、代码中难点及相关资料介绍、与当 前版本的主要区别等部分。最后一章内容总结性地介绍了继续研究Linux系统的方法和着手点。 版权说明 作者保留本电子书籍的修改和正式出版的所有权利.读者可以自由传播本书全部和部分章节的内容,但需要注明出处.由 于目前本书尚为草稿阶段,因此存在许多错误和不足之处,希望读者能踊跃给予批评指正或建议.可以通过电子邮件给我发信 息:[email protected], 或直接来信至:上海同济大学 机械电子工程研究所(上海四平路1239号,邮编:200092). © 2002,2003,2004 by Zhao Jiong © 2002,2003,2004 赵炯 版权所有. “RTFSC – Read The F**king Source Code ☺!” –Linus Benedict Torvalds 目录 目录 5.3 MAKEFILE文件...................................................98 序言................................................................................1 5.4 ASM.S程序........................................................100 本书的主要目标........................................................1 5.5 TRAPS.C程序.....................................................106 现有书籍不足之处....................................................1 5.6 SYSTEM_CALL.S程序........................................113 阅读早期内核的其它好处........................................2 5.7 MKTIME.C程序.................................................123 阅读完整源代码的重要性和必要性........................2 5.8 SCHED.C程序....................................................125 如何选择要阅读的内核代码版本............................3 5.9 SIGNAL.C程序...................................................138 阅读本书需具备的基础知识....................................3 5.10 EXIT.C程序.....................................................147 使用早期版本是否过时?........................................4 5.11 FORK.C程序....................................................153 EXT2文件系统与MINIX文件系统.........................4 5.12 SYS.C程序.......................................................160 第1章 概述..................................................................5 5.13 VSPRINTF.C程序..............................................166 5.14 PRINTK.C程序.................................................174 1.1 LINUX的诞生和发展...........................................5 5.15 PANIC.C程序...................................................175 1.2 内容综述...........................................................10 5.16 本章小结........................................................176 1.3 本章小结...........................................................14 第6章 块设备驱动程序(BLOCK DRIVER).........177 第2章 LINUX内核体系结构..................................15 6.1 概述.................................................................177 2.1 LINUX内核模式.................................................15 6.2 总体功能..........................................................177 2.2 LINUX内核系统体系结构.................................16 6.3 MAKEFILE文件.................................................180 2.3 中断机制...........................................................18 6.4 BLK.H文件........................................................182 2.4 系统定时...........................................................19 6.5 HD.C程序..........................................................186 2.5 LINUX进程控制.................................................20 6.6 LL_RW_BLK.C程序...........................................202 2.6 LINUX内核对内存的使用方法.........................26 6.7 RAMDISK.C程序................................................207 2.7 LINUX系统中堆栈的使用方法.........................29 6.8 FLOPPY.C程序...................................................212 2.8 LINUX内核源代码的目录结构.........................32 第7章 字符设备驱动程序(CHAR DRIVER).......239 2.9 内核系统与用户程序的关系............................38 2.10 LINUX/MAKEFILE文件......................................39 7.1 概述.................................................................239 2.11 本章小结..........................................................47 7.2 总体功能描述..................................................239 第3章 引导启动程序(BOOT).............................49 7.3 MAKEFILE文件.................................................247 7.4 KEYBOARD.S程序.............................................249 3.1 概述...................................................................49 7.5 CONSOLE.C程序................................................267 3.2 总体功能...........................................................49 7.6 SERIAL.C程序...................................................290 3.3 BOOTSECT.S程序................................................50 7.7 RS_IO.S程序.....................................................293 3.4 SETUP.S程序.......................................................58 7.8 TTY_IO.C程序...................................................297 3.5 HEAD.S程序........................................................71 7.9 TTY_IOCTL.C程序.............................................308 3.6 本章小结...........................................................80 第8章 数学协处理器(MATH)................................317 第4章 初始化程序(INIT).........................................81 8.1 概述.................................................................317 4.1 概述...................................................................81 8.2 MAKEFILE文件.................................................317 4.2 MAIN.C程序........................................................81 8.3 MATH-EMULATION.C程序..................................319 4.3 环境初始化工作...............................................91 第9章 文件系统(FS)...............................................321 4.4 本章小结...........................................................92 第5章 内核代码(KERNEL).....................................95 9.1 概述.................................................................321 9.2 总体功能描述..................................................321 5.1 概述...................................................................95 9.3 MAKEFILE文件.................................................327 5.2 总体功能描述...................................................95 - I - 目录 9.4 BUFFER.C程序..................................................330 11.27 KERNEL.H文件..............................................526 9.5 BITMAP.C程序...................................................345 11.28 MM.H文件.....................................................527 9.6 INODE.C程序....................................................349 11.29 SCHED.H文件................................................527 9.7 SUPER.C程序....................................................360 11.30 SYS.H文件.....................................................535 9.8 NAMEI.C程序....................................................369 11.31 TTY.H文件.....................................................537 9.9 FILE_TABLE.C程序............................................390 11.32 INCLUDE/SYS/目录中的文件.........................540 9.10 BLOCK_DEV.C程序.........................................390 11.33 STAT.H文件...................................................540 9.11 FILE_DEV.C程序..............................................394 11.34 TIMES.H文件.................................................541 9.12 PIPE.C程序......................................................397 11.35 TYPES.H文件.................................................542 9.13 CHAR_DEV.C程序...........................................400 11.36 UTSNAME.H文件...........................................543 9.14 READ_WRITE.C程序........................................403 11.37 WAIT.H文件...................................................544 9.15 TRUNCATE.C程序............................................407 第12章 库文件(LIB)...............................................547 9.16 OPEN.C程序....................................................409 9.17 EXEC.C程序....................................................415 12.1 概述...............................................................547 9.18 STAT.C程序.....................................................430 12.2 MAKEFILE文件...............................................548 9.19 FCNTL.C程序..................................................431 12.3 _EXIT.C程序...................................................550 9.20 IOCTL.C程序...................................................434 12.4 CLOSE.C程序..................................................550 12.5 CTYPE.C程序..................................................551 第10章 内存管理(MM)..........................................437 12.6 DUP.C程序......................................................552 10.1 概述...............................................................437 12.7 ERRNO.C程序..................................................553 10.2 总体功能描述...............................................437 12.8 EXECVE.C程序................................................553 10.3 MAKEFILE文件...............................................442 12.9 MALLOC.C程序...............................................554 10.4 MEMORY.C程序...............................................443 12.10 OPEN.C程序..................................................562 10.5 PAGE.S程序.....................................................457 12.11 SETSID.C程序................................................563 12.12 STRING.C程序...............................................564 第11章 头文件(INCLUDE)...................................459 12.13 WAIT.C程序...................................................564 11.1 概述...............................................................459 12.14 WRITE.C程序................................................565 11.2 INCLUDE/目录下的文件.................................459 第13章 建造工具(TOOLS)....................................567 11.3 A.OUT.H文件...................................................460 11.4 CONST.H文件..................................................470 13.1 概述...............................................................567 11.5 CTYPE.H文件..................................................471 13.2 BUILD.C程序...................................................567 11.6 ERRNO.H文件.................................................472 第14章 实验环境设置与使用方法........................574 11.7 FCNTL.H文件..................................................474 11.8 SIGNAL.H文件.................................................476 14.1 概述...............................................................574 11.9 STDARG.H文件................................................478 14.2 BOCHS仿真系统............................................574 11.10 STDDEF.H文件..............................................479 14.3 创建磁盘映象文件........................................578 11.11 STRING.H文件...............................................480 14.4 访问磁盘映象文件中的信息........................581 11.12 TERMIOS.H文件............................................490 14.5 制作根文件系统............................................584 11.13 TIME.H文件...................................................497 14.6 在LINUX 0.11系统上编译0.11内核...........590 11.14 UNISTD.H文件...............................................498 14.7 在REDHAT 9系统下编译LINUX 0.11内核..591 11.15 UTIME.H文件................................................504 14.8 利用BOCHS调试内核...................................594 11.16 INCLUDE/ASM/目录下的文件.......................505 参考文献....................................................................595 11.17 IO.H文件.......................................................505 11.18 MEMORY.H文件.............................................506 附录............................................................................596 11.19 SEGMENT.H文件...........................................507 附录1 内核主要常数............................................596 11.20 SYSTEM.H文件..............................................509 附录2 内核数据结构............................................599 11.21 INCLUDE/LINUX/目录下的文件....................512 附录3 80X86保护运行模式.................................607 11.22 CONFIG.H文件...............................................512 附录4 ASCII码表.................................................617 11.23 FDREG.H头文件............................................514 11.24 FS.H文件.......................................................517 索引............................................................................618 11.25 HDREG.H文件................................................523 11.26 HEAD.H文件.................................................525 - II - 序言 序言 本书是一本有关Linux操作系统内核基本工作原理的入门读物。 本书的主要目标 本书的主要目标是使用尽量少的篇幅或在有限的篇幅内,对完整的 Linux 内核源代码进行解剖,以 期对操作系统的基本功能和实际实现方式获得全方位的理解。做到对 linux 内核有一个完整而深刻的理 解,对linux操作系统的基本工作原理真正理解和入门。 本书读者群的定位是一些知晓 Linux 系统的一般使用方法或具有一定的编程基础,但比较缺乏阅读 目前最新内核源代码的基础知识,又急切希望能够进一步理解UNIX类操作系统内核工作原理和实际代 码实现的爱好者。这部分读者的水平应该界于初级与中级水平之间。目前,这部分读者人数在 Linux 爱 好者中所占的比例是很高的,而面向这部分读者以比较易懂和有效的手段讲解内核的书籍资料不多。 现有书籍不足之处 目前已有的描述Linux内核的书籍,均尽量选用最新Linux内核版本(例如Redhat 7.0使用的2.2.16 稳定版等)进行描述,但由于目前 Linux 内核整个源代码的大小已经非常得大(例如 2.2.20 版具有 268 万行代码!),因此这些书籍仅能对 Linux 内核源代码进行选择性地或原理性地说明,许多系统实现细节 被忽略。因此并不能给予读者对实际Linux内核有清晰而完整的理解。 Scott Maxwell著的一书《Linux内核源代码分析》(陆丽娜等译)基本上是面对Linux中级水平的读 者,需要较为全面的基础知识才能完全理解。而且可能是由于篇幅所限,该书并没有对所有 Linux 内核 代码进行注释,略去了很多内核实现细节,例如其中内核中使用的各个头文件(*.h)、生成内核代码映象 文件的工具程序、各个 make 文件的作用和实现等均没有涉及。因此对于处于初中级水平之间的读者来 说阅读该书有些困难。 浙江大学出版的《Linux 内核源代码情景分析》一书,也基本有这些不足之处。甚至对于一些具有 较高 Linux 系统应用水平的计算机本科高年级学生,由于该书篇幅问题以及仅仅选择性地讲解内核源代 码,也不能真正吃透内核的实际实现方式,因而往往刚开始阅读就放弃了。这在本人教学的学生中基本 都会出现这个问题。该书刚面市时,本人曾极力劝说学生购之阅读,并在二个月后调查阅读学习情况, 基本都存在看不下去或不能理解等问题,大多数人都放弃了。 John Lions著的《莱昂氏UNIX源代码分析》一书虽然是一本学习UNIX类操作系统内核源代码很 好的书籍,但是由于其采用的是UNIX V6版,其中系统调用等部分代码是用早已过时的PDP-11系列机 的汇编语言编制的,因此在阅读与硬件部分相关的源代码时就会遇到较大的困难。 A.S.Tanenbaum 的书《操作系统:设计与实现》是一本有关操作系统内核实现很好的入门书籍,但 该书所叙述的MINIX系统是一种基于消息传递的内核实现机制,与Linux内核的实现有所区别。因此在 学习该书之后,并不能很顺利地即刻着手进一步学习较新的Linux内核源代码实现。 在使用这些书籍进行学习时会有一种“盲人摸象”的感觉,不能真正理解 Linux 内核系统具体实现 的整体概念,尤其是对那些 Linux 系统初学者或刚学会如何使用 Linux 系统的人在使用那些书学习内核 - 1 - 序言 原理时,内核的整体运作结构并不能清晰地在脑海中形成。这在本人多年的 Linux 内核学习过程中也深 有体会。在1991年10月份,Linux的创始人Linus Toravlds在开发出Linux 0.03版后写的一篇文章中也 提到了同样的问题。在这篇题为“LINUX--a free unix-386 kernel”的文章中,他说:“开发Linux是为了 那些操作系统爱好者和计算机科学系的学生使用、学习和娱乐。...自由软件基金会的GNU Hurd系统如 果开发出来就已经显得太庞大而不适合学习和理解。”而现今的 Linux 系统要比 GNU 的 Hurd 系统更为 庞大和复杂,因此同样也已经不适合作为操作系统初学者的入门学习起点。这也是写作本书的动机之一。 为了填补这个空缺,本书的主要目标是使用尽量少的篇幅或在有限的篇幅内,对完整的 Linux 内核 源代码进行全面解剖,以期对操作系统的基本功能和实际实现方式获得全方位的理解。做到对 Linux 内 核有一个完整而深刻的理解,对Linux操作系统的基本工作原理真正理解和入门。 阅读早期内核的其它好处 目前,已经出现不少基于 Linux 早期内核而开发的专门用于嵌入式系统的内核版本,如 DJJ 的 x86 操作系统、Uclinux等(在www.linux.org上有专门目录),世界上也有许多人认识到通过早期Linux内核 源代码学习的好处,目前国内也已经有人正在组织人力注释出版类似本文的书籍。因此,通过阅读Linux 早期内核版本的源代码,的确是学习 Linux 系统的一种行之有效的途径,并且对研究和应用 Linux 嵌入 式系统也有很大的帮助。 在对早期内核源代码的注释过程中,作者发现,早期内核源代码几乎就是目前所使用的较新内核的 一个精简版本。其中已经包括了目前新版本中几乎所有的基本功能原理的内容。正如《系统软件:系统 编程导论》一书的作者Leland L. Beck在介绍系统程序以及操作系统设计时,引入了一种极其简化的简 单指令计算机(SIC)系统来说明所有系统程序的设计和实现原理,从而既避免了实际计算机系统的复杂 性,又能透彻地说明问题。这里选择Linux的早期内核版本作为学习对象,其指导思想与Leland的一致。 这对 Linux 内核学习的入门者来说,是最理想的选择之一。能够在尽可能短的时间内深入理解 Linux 内 核的基本工作原理。 对于那些已经比较熟悉内核工作原理的人,为了能让自己在实际工作中对系统的实际运转机制不产 生一种空中楼阁的感觉,因此也有必要阅读内核源代码。 当然,使用早期内核作为学习的对象也有不足之处。所选用的 Linux 早期内核版本不包含对虚拟文 件系统 VFS 的支持、对网络系统的支持、仅支持 a.out 执行文件和对其它一些现有内核中复杂子系统的 说明。但由于本书是作为 Linux 内核工作机理实现的入门教材,因此这也正是选择早期内核版本的优点 之一。通过学习本书,可以为进一步学习这些高级内容打下扎实的基础。 阅读完整源代码的重要性和必要性 正如 Linux 系统的创始人在一篇新闻组投稿上所说的,要理解一个软件系统的真正运行机制,一定 要阅读其源代码(RTFSC – Read The Fucking Source Code)。系统本身是一个完整的整体,具有很多看似 不重要的细节存在,但是若忽略这些细节,就会对整个系统的理解带来困难,并且不能真正了解一个实 际系统的实现方法和手段。 虽然通过阅读一些操作系统原理经典书籍(例如M.J.Bach的《UNIX操作系统设计》)能够对UNIX 类操作系统的工作原理有一些理论上的指导作用,但实际上对操作系统的真正组成和内部关系实现的理 解仍不是很清晰。正如 AST 所说的,“许多操作系统教材都是重理论而轻实践”,“多数书籍和课程为调 度算法耗费大量的时间和篇幅而完全忽略 I/O,其实,前者通常不足一页代码,而后者往往要占到整个 系统三分之一的代码总量。”内核中大量的重要细节均未提到。因此并不能让读者理解一个真正的操作系 统实现的奥妙所在。只有在详细阅读过完整的内核源代码之后,才会对系统有一种豁然开朗的感觉,对 - 2 - 序言 整个系统的运作过程有深刻的理解。以后再选择最新的或较新内核源代码进行学习时,也不会碰到大问 题,基本上都能顺利地理解新代码的内容。 如何选择要阅读的内核代码版本 那么,如何选择既能达到上述要求,又不被太多的内容而搞乱头脑,选择一个适合的 Linux 内核版 本进行学习,提高学习的效率呢?作者通过对大量内核版本进行比较和选择后,最终选择了与目前Linux 内核基本功能较为相近,又非常短小的 0.11 版内核作为入门学习的最佳版本。下图是对一些主要 Linux 内核版本行数的统计。 10000000 1000000 100000 10000 1000 1 1 2 5 a 7 0 2 3 5 8 0 7 0 1 1 9 6 9 . 5 1 9 3 2 1 . . . . 9 . 1 . . . . . . 0 0 0 0 . 0 V 1 2 3 0 2 4 V V V V 0 V . . . . . . V 1 1 1 2 2 2 V V V V V V 目前的 Linux 内核源代码量都在几百万行的数量上,极其庞大,对这些版本进行完全注释和说明几 乎是不可能的,而0.11版内核不超过2万行代码量,因此完全可以在一本书中解释和注释清楚。麻雀虽 小,五脏俱全。 另外,使用该版本可以避免使用现有较新内核版本中已经变得越来越复杂得各子系统部分的研究(如 虚拟文件系统VFS、ext2或ext3文件系统、网络子系统、新的复杂的内存管理机制等)。 阅读本书需具备的基础知识 在阅读本书时,作者希望读者具有以下一些基础知识或有相关的参考书籍在手边。其一是有关80x86 处理器结构和编程的知识或资料。例如可以从网上下载的 80x86 编程手册(INTEL 80386 Programmer's Reference Manual);其二是有关80x86硬件体系结构和接口编程的知识或资料。有关这方面的资料很多; 其三还应具备初级使用Linux系统的简单技能。 另外,由于Linux系统内核实现,最早是根据M.J.Bach的《UNIX操作系统设计》一书的基本原理 - 3 - 序言 开发的,源代码中许多变量或函数的名称都来自该书,因此在阅读本书时,若能适当参考该书,更易于 对源代码的理解。 Linus在最初开发Linux操作系统时,参照了MINIX操作系统。例如,最初的Linux内核版本完全 照搬了MINIX 1.0文件系统。因此,在阅读本书时,A.S.Tanenbaum的书《操作系统:设计与实现》也 具有较大的参考价值。但Tanenbaum的书描述的是一种基于消息传递在内核各模块之间进行通信(信息 交换),这与Linux内核的工作机制不一样。因此可以仅参考其中有关一般操作系统工作原理章节和文件 系统实现的内容。 使用早期版本是否过时? 表面看来本书对Linux早期内核版本注释的内容犹如Linux操作系统刚公布时Tanenbaum就认为其 已经过时的(Linux is obsolete)想法一样,但通过学习本书内容,你就会发现,利用本书学习Linux内 核,由于内核源代码量短小而精干,因此会有极高的学习效率,能够做到事半功倍,快速入门。并且对 继续进一步选择新内核部分源代码的学习打下坚实的基础。在学习完本书之后,你将对系统的运作原理 有一个非常完整而实际的概念,这种完整概念能使人很容易地进一步选择和学习新内核源代码中的任何 部分,而不需要再去啃读代码量巨大的新内核中完整的源代码。 Ext2 文件系统与 MINIX 文件系统 目前Linux系统上所使用的Ext2(或最新的Ext3)文件系统,是在内核1.x之后开发的文件系统, 其功能详尽并且其性能也非常完整和稳固,是目前 Linux 操作系统上默认的标准文件系统。但是,作为 对 Linux 操作系统完整工作原理入门学习所使用的部分,原则上是越精简越好。为了达到对一个操作系 统有完整的理解,并且能不被其中各子系统中的复杂性和过多的细节喧宾夺主,在选择学习剖析用的内 核版本时,只要系统的部分代码内容能说明实际工作原理,就越简单越好。 Linux内核0.11版上当时仅包含最为简单的MINIX 1.0文件系统,对于理解一个操作系统中文件系 统的实际组成和工作原理已经足够。这也是选择Linux早期内核版本进行学习的主要原因之一。 在完整阅读完本书之后,相信您定会发出这样的感叹:“对于Linux内核系统,我现在终于入门了!”。 此时,您应该有十分的把握去进一步学习最新Linux内核中各部分的工作原理和过程了。 同济大学 赵炯 博士 2002.12 - 4 -