Linux内核设计与实现(原书第3版)-第1~3章

所需积分/C币:10 2011-10-09 11:12:27 1.83MB PDF
0
收藏 收藏
举报

Linux内核设计与实现(原书第3版)-第1~3章
Linux内核简介 3 Linus像任何一名生机勃勃的大学生一样决心走岀这种困境:开发自己的操作系统。他开始 写了一个简单的终端仿真程序,用于连接到本校的大型Unⅸx系统上。他的终端仿真程序经过 学年的研发,不断改进和完善。不久, Linus手上就有了虽不成熟但五脏俱全的Unix。1991年年 底,他在 Internet上发布了早期版本 从此 Linux便起航了,最初的 Linux发布很快赢得了众多用户。而实际上,它成功的重要因 素是, Linux很快吸引了很多开发者、黑客对其代码进行修改和完善。由于其许可证条款的约定 Linux迅速成为多人的合作开发项目。 到现在, Linux早已羽翼丰满,它被广泛移植到 Alpha、ARM、 PowerPc、 SPARC、x86-64 等许多其他体系结构之上。如今 Linux既被安装在最轻小的消费电子设备上,比如手表,同时也 在服务规模最庞大的服务数据中心上,如超级计算机集群。今天, Linux的商业前景也越来越被 看好,不管是新成立的 Linux专业公司 Red hat还是闻名遐迩的计算巨头IBM,都提供林林总总 的解决方案,从嵌入式系统、桌面环境一直到服务器。 Linux是类Unⅸx系统,但它不是Unix。需要说明的是,尽管 Linux借鉴了Unix的许多设计 并且实现了Unix的API(由 Posix标准和其他 Single Unix Specification定义的),但 Linux没有 像其他Unⅸx变种那样直接使用Uniⅸx的源代码。必要的时候,它的实现可能和其他各种Unix的 实现大相径庭,但它没有抛弃Unⅸx的设计目标并且保证了应用程序编程接口的一致。 Linux是一个非商业化的产品,这是它最让人感兴趣的特征。实际上 Linux是一个互联网上 的协作开发项目。尽管 Linus被认为是 Linux之父,并且现在依然是一个内核维护者,但开发工 作其实是由一个结构松散的工作组协力完成的。事实上,任何人都可以开发内核。和该系统的 大部分一样,Linx内核也是自由(公开)软件⊙。当然,也不是无限自由的。它使用GNU的 General public license(GPL)第2版作为限制条款。这样做的结果是,你可以自由地获取内核 代码并随意修改它,但如果你希望发布你修改过的内核,你也得保证让得到你的内核的人同时享 有你曾经享受过的所有权利,当然,包括全部的源代码。 Linux用途广泛,包含的东西也名目繁多。 Linux系统的基础是内核、C库、工具集和系统 的基本工具,如登录程序和 Shell linux系统也支持现代的 X Windows系统,这样就可以使用完 整的图形用户桌面环境,如 GNOME。可以在 Linux上使用的商业和自由软件数以千计。在这本书 以后的部分,当我使用 Linux这个词时,我其实说的是 Linux内核。在容易引起混淆的地方,我会 具体说明到底我想说的是整个系统还是内核。一般情况下, Linux这个词汇主要还是指内核。 1.3操作系统和内核简介 由于一些现行商业操作系统日趋庞杂及其设计上的缺陷,操作系统的精确定义并没有一个统 的标准。许多用户把他们在显示器屏幕上看到的东西理所当然地认为就是操作系统。通常,当 ⊙谁有兴趣了解freeVSopen的论战,请参见http://www.fsf.organdhttp://www.opensource.org ③如果你没有读过 GNU GPL2.0,你最好还是先读读它吧。内核代码树种的. COPYING文件就是它的一份拷 贝。你也可以在http://www.fsf.org找到它。注意最新的GNUGPL已经是3.0版本了,但内核开发者们仍然决 定继续使用2.0版本 第1章 然在本书中也这么认为,操作系统是指在整个系统中负责完成最基本功能和系统管理的那些部 分。这些部分应该包括内核、设备驱动程序、启动引导程序、命令行Shel或者其他种类的用户 界面、基本的文件管理工具和系统工具。这些都是必不可少的东西—别以为只要有浏览器和播 放器就行了。系统这个词其实包含了操作系统和所有运行在它之上的应用程序。 当然,本书的主题是内核。用户界面是操作系统的外在表象,内核才是操作系统的内在核 心。系统其他部分必须依靠内核这部分软件提供的服务,像管理硬件设备、分配系统资源等。 内核有时侯被称作是管理者或者是操作系统核心。通常一个内核由负责响应中断的中断服务程 序,负责管理多个进程从而分享处理器时间的调度程序,负责管理进程地址空间的内存管理程 序和网络、进程间通信等系统服务程序共同组成。对于提供保护机制的现代系统来说,内核独 立于普通应用程序,它一般处于系统态,拥有受保护的內存空间和访问硬件设备的所有权限 这种系统态和被保护起来的内存空间,统称为内核空间。相对的,应用程序在用户空间执行 它们只能看到允许它们使用的部分系统资源,并且只使用某些特定的系统功能,不能直接访问 硬件,也不能访问内核划给别人的内存范围,还有其他一些使用限制。当内核运行的时候,系 统以内核态进入内核空间执行。而执行一个普通用户程序时,系统将以用户态进入以用户空间 执行 在系统中运行的应用程序通过系统调用来与内核通信(见图1-1)。应用程序通常调用库函 数(比如C库函数)再由库函数通过系统调用界面,让内核代其完成各种不同任务。一些库调 用提供了系统调用不具备的许多功能,在那些较为复杂的函数中,调用内核的操作通常只是整 个工作的一个步骤而已。举个例子,拿 printf()函数来说,它提供了数据的缓存和格式化等操作 而调用 write(函数将数据写到控制台上只不过是其中的一个动作罢了。不过,也有一些库函数 和系统调用就是一一对应的关系,比如, open库函数除了调用open(系统调用之外,几乎什么 也不做。还有一些C库函数,像 strcpy(,根本就不需要直接调用系统级的操作。当一个应用程 序执行一条系统调用,我们说内核正在代其执行。如果进一步解释,在这种情况下,应用程序被 称为通过系统调用在内核空间运行,而內核被称为运行于进程上下文中。这种交互关系—一应用 程序通过系统调用界面陷入内核——是应用程序完成其工作的基本行为方式 内核还要负责管理系统的硬件设备。现有的几乎所有的体系结构,包括全部 Linux支持的体 系结构,都提供了中断机制。当硬件设备想和系统通信的时候,它首先要发出一个异步的中断 信号去打断处理器的执行,继而打断内核的执行。中断通常对应着一个中断号,内核通过这个 中断号査找相应的中断服务程序,并调用这个程序响应和处理中断。举个例子,当你敲击键盘 的时候,键盘控制器发送一个中断信号告知系统,键盘缓冲区有数据到来。内核注意到这个中 断对应的中断号,调用相应的中断服务程序。该服务程序处理键盘数据然后通知键盘控制器可 以继续输入数据了。为了保证同步,内核可以停用中止——既可以停止所有的中断也可以有选 择地停止某个中断号对应的中断。许多操作系统的中断服务程序,包括 Linux的,都不在进程 上下文中执行。它们在一个与所有进程都无关的、专门的中断上下文中运行。之所以存在这样 个专门的执行环境,就是为了保证中断服务程序能够在第一时间响应和处理中断请求,然后 快速地退出。 这些上下文代表着内核活动的范围。实际上我们可以将每个处理器在任何指定时间点上的活 Linux内核简介 动必然概括为下列三者之一: 应用程序1 应用程序2 应用程序3 用户空间 系统调用接口 内核空间 内核子系统 设备驱动程序 硬件 图1-1应用程序、内核和硬件的关系 运行于用户空间,执行用户进程 运行于内核空间,处于进程上下文,代表某个特定的进程执行 运行于内核空间,处于中断上下文,与任何进程无关,处理某个特定的中断。 以上所列几乎包括所有情况,即使边边角角的情况也不例外,例如,当CPU空闲时,内核 就运行一个空进程,处于进程上下文,但运行于内核空间。 1.4 Linux内核和传统∪nix内核的比较 由于所有的Uniⅸx内核都同宗同源,并且提供相同的API,现代的Unix内核存在许多设计上 的相似之处(请看参考目录中我所推荐的关于传统Unx内核设计的相关书籍)。Unix内核几乎 亳无例外的都是一个不可分割的静态可执行库。也就是说,它们必须以巨大、单独的可执行块 的形式在一个单独的地址空间中运行。Unⅸx内核通常需要硬件系统提供页机制(MMU)以管理 内存。这种页机制可以加强对内存空间的保护,并保证每个进程都可以运行于不同的虚地址空间 上。初期的 Linux系统也需要MMU支持,但有一些特殊版本并不依赖于此。这无疑是一个简洁 的设计,因为它可以使 Linux系统运行在没有MMU的小型嵌入系统上。不过现实之中,即便很 简单的嵌入系统都开始具备内存管理单元这种高级功能了。本书中,我们将重点关注支持MMU 的 Linux系统 第1章 单内核与微内核设计之比较 操作系统内核可以分为两大阵营:单内核和微内核(第三阵营是外内核,主要用在科硏 系统中)。 单内核是两大阵营中一种较为简单的设计,在1980年之前,所有的内核都设计成单内 核。所谓单內核就是把它从整体上作为一个单独的大过程来实现,同时也运行在一个单独的地 址空间上。因此,这样的内核通常以单个静态二进制文件的形式存放于磁盘中。所有内核服务 都在这样的一个大内核地址空间上运行。内核之间的通信是微不足道的,因为大家都运行在内 核态,并身处同一地址空间:内核可以直接调用函数,这与用户空间应用程序没有什么区别 这种模式的支持者认为单模块具有简单和性能高的特点。大多数Unix系统都设计为单模块。 另一方面,微内核并不作为一个单独的大过程来实现。相反,微内核的功能被划分为多 个独立的过程,每个过程叫做一个服务器。理想情况下,只有强烈请求特权服务的服务器才 运行在特权模式下,其他服务器都运行在用户空间。不过,所有的服务器都保持独立并运行 在各自的地址空间上。因此,就不可能像单模块内核那样直接调用函数,而是通过消息传递处 理微内核通信:系统采用了进程间通信(IPC)机制,因此,各个服务器之间通过IPC机制 互通消息,互换“服务”。服务器的各自独立有效地避免了一个服务器的失效祸及另一个。同 样,模块化的系统允许一个服务器为了另一个服务器而换出。 因为IPC机制的开销多于函数调用,又因为会涉及内核空间与用户空间的上下文切换,因 此,消息传递需要一定的周期,而单內核中简单的函数调用没有这些开销。结果,所有实际应 用的基于微内核的系统都让大部分或全部服务器位于内核,这样,就可以直接调用函数,消 除频繁的上下文切换。 Windows nt内核( Windows Xp、 WindowsⅤista和 Windows7等基于此) 和Mach( Mac OsⅩ的组成部分)是微内核的典型实例。不管是 Windows nt还是 Mac OsX 都在其新近版本中不让任何微内核服务器运行在用户空间,这违背了微内核设计的初衷。 Linux是一个单内核,也就是说, Linux内核运行在单独的内核地址空间上。不过, Linux 汲取了微内核的精华:其引以为豪的是模块化设计、抢占式内核、支持内核线程以及动态装 载内核模块的能力。不仅如此, Linux还避其微内核设计上性能损失的缺陷,让所有事情都运 行在内核态,直接调用函数,无须消息传递。至今, Linux是模块化的、多线程的以及内核本 身可调度的操作系统,实用主义再次占了上风 当 Linus和其他内核开发者设计 Linux内核时,他们并没有完全彻底地与Unix诀别。他们 充分地认识到,不能忽视Unix的底蕴(特别是Unix的APⅠ)。而由于 Linux并没有基于某种 特定的Unⅸx, Linus和他的伙伴们对毎个特定的问题都可以选择已知最理想的解决方案——在 有些时候,当然也可以创造一些新的方案。 Linux内核与传统的Unix系统之间存在一些显著的 差异: · Linux支持动态加载内核模块。尽管 Linux内核也是单内核,可是允许在需要的时候动态 地卸除和加载部分内核代码。 · Linux支持对称多处理(SMP)机制,尽管许多Unix的变体也支持SMP,但传统的Unix 并不支持这种机制 Linux内核简介 7 · Linux内核可以抢占( preemptive)。与传统的Uniⅸx变体不同, Linux內核具有允许在内核 运行的任务优先执行的能力。在其他各种Unix产品中,只有 Solaris和IRIX支持抢占, 但是大多数Unix内核不支持抢占 Linux对线程支持的实现比较有意思:内核并不区分线程和其他的一般进程。对于内核来 说,所有的进程都一样——只不过是其中的一些共享资源而已 · Linux提供具有设备类的面向对象的设备模型、热插拔事件,以及用户空间的设备文件系 统( sysfs) Linux忽略了一些被认为是设计得很拙劣的Unⅸx特性,像 STREAMS,它还忽略了那些难 以实现的过时标准。 Linux体现了自由这个词的精髓。现有的 Linux特性集就是Linuκ公开开发模型自由发展 的结果。如果一个特性没有任何价值或者创意很差,没有任何人会被迫去实现它。相反 的,针对变革, Linux已经形成了一种值得称赞的态度:任何改变都必须要能通过简洁的 设计及正确可靠的实现来解决现实中确实存在的问题。于是,许多出现在某些Unⅸx变种 系统中,那些出于市场宣传目的或没有普遍意义的一些特性,如內核换页机制等都被毫不 迟疑地摒弃了。 不管 Linux和Unix有多大的不同,它身上都深深地打上了Unix烙印。 1.5 Linux内核版本 Linux内核有两种:稳定的和处于开发中的。稳定的内核具有工业级的强度,可以广泛地应 用和部署。新推出的稳定内核大部分都只是修正了一些Bug或是加入了一些新的设备驱动程序。 另一方面处于开发中的内核中许多东西变化得都很快。而且由于开发者不断试验新的解决方案, 内核常常发生剧烈的变化。 Linux通过一个简单的命名机制来区分稳定的和处于开发中的内核(见图1-2)。这种机制使 用三个或者四个用“”分隔的数字来代表不同内核版本。第一个数字是主版本号,第二个数字 是从版本号,第三个数字是修订版本号,第四个可选的数字为稳定版本号( stable version)。从副 版本号可以反映出该内核是一个稳定版本还是一个处于开发中的版本:该数字如果是偶数,那么 此内核就是稳定版;如果是奇数,那么它就是开发版。举例来说,版本号为2.6.30.1的内核,它 就是一个稳定版。这个内核的主版本号是2,从版本号是6,修订版本号是30,稳定版本号是1。 头两个数字在一起描述了“内核系列”——在这个例子中,就是2.6版内核系列 主版本号修订版本号 2.6.26.1 从版本号 稳定版本号 图1-2 Kernel版本命名规贝 8 第1章 处于开发中的内核一般要经历几个阶段。最开始,内核开发者们开始试验新的特性,这时候 出现错误和混乱是在所难免的。经过一段时间,系统渐渐成熟,最终会有一个特性审定的声明。 这时候, Linus就不再接受新的特性了,而对已有特性所进行的后续工作会继续进行。当 Linus 认为这个新内核确实是趋于稳定后,就开始审定代码。这以后,就只允许再向其中加入修改bug 的代码了。在经过一个短暂(希望如此)的准备期之后, Linus会将这个內核作为一个新的稳定 版推出。例如,1.3系列的开发版稳定在2.0,而2.5稳定在2.6。 在一个特定的系列下, Linus会定期发布新内核。每个新内核都是一个新的修订版本。比如 2.6内核系列的第一个版本是2.6.0,第二个版本是2.6.1。这些修订版包含了BUG修复、新的驱 动和一些新特性。但是,像2.6.3和2.6.4修订版本之间的差异是很微小的。 这种开发方式一直持续到2004年,当时在受邀参加的 Linux开发者峰会上,内核开发者们 确定延长2.6内核系列,从而推迟进入到2.7系列的步伐。原因是2.6版本的内核巳经被广泛接 受、其已经证明了稳定成熟,而那些还不成熟的新特性其实并非人们所需。如今看来2.6版本内 核的稳定出色无疑证明了该方针是多么英明。在编写本书时,2.7版本内核仍未提上议程,而且 也看不出任何启动迹象。相反,每个2.6系列内核的修订版本发布变得越发长久,每个修订版都 伴随有一个最小的开发版系列(称其微缩开发版)。 Andrew morton, Linus的副手,重新定义了 他所维护的2.6-mm代码树(它曾经用于内存管理相关改动的测试版本),使其成为一个通用目 的的测试版本。任何尚未稳定的修改都将首先进入2.6-mm树中,等其稳定后,再进入某个2.6 的微缩开发版。如此策略的结果是:最近几年,每一个2.6系列的修订版本(比如2.6.29)都会 较其前身有深刻的变化,也都会经历数月才面世。这种“微缩开发版方式”被证明是可行的、成 功的,它更有利于在引入新特性的同时,维持系统的稳定性。想必在近期内开发策略不会改弦易 辙,事实上内核开发者们就新版本的发布流程延续目前方式已经达成了一致意见。 为了解决版本发布周期变长的副作用,内核开发者们引入了上面提到的稳定版本号。这个 稳定版本号(如2.6.32.8中的8)包含了关键性bug的修改,并且常会向前移植处于开发版内核 (如2.6.33)的重要修改。依靠这种方式,以前版本保证了仍然能将重点放在稳定性上。 1.6 Linux内核开发者社区 当你开始开发內核代码时,你就成为全球内核开发社区的一分子了。这个社区最重要的论坛 是linuxkernelmailinglist常缩写为lkml)o你可以在http:/vegr.kernelorg上订阅邮件。要注意 的是这个邮件列表流量很大,每天有超过几百条的消息,所以其他的订阅者(包括所有的核心开 发人员,甚至包括 Linus本人)可没有心思听人说废话。这个邮件列表可以给从事内核开发的人 提供价值无穷的帮助,在这里,你可以寻找测试人员,接受评论( peer review),向人求助 后续内容列出了内核开发过程的全景,并详尽地描述了如何成功地加入到内核开发社区中 去。但是要明白,在 Linux内核邮件列表中潜伏(安静地阅读)是你阅读本书的最好补充。 1.7小结 这是一本关于 Linux内核的书:内核的目标,为达到目标所进行的设计以及设计的实现。这 本书侧重实用,同时在讲述工作原理时会结合理论联系实践。我的目标是让你从一个业内人士的 Linux内核简介 9 视角来欣赏和理解 Linux内核的设计和实现之美。力求以一种有趣的方式(伴随着我个人在开 发内核过程中收集的种种奇闻逸事和方法技巧)引导你走过跌跌撞撞的起步阶段。无论你是立 志于开发内核代码,或者进行驱动开发,甚至只是希望能更好地了解 Linux操作系统,你都将 从本书受益。 当你阅读本书时,我希望你有一台装有 Linux的机器,我希望你能够看到内核代码。其实, 这很理想了,因为这意味着你是一位 Linux的使用者,并且早已经开始拿起手术刀对着源代码进 行探索了,只不过需要一份结构图以便对整个经脉有个总体把握罢了。相反,你可能没有使用过 Linux,只是在好奇心的驱使下希望了解一些内核设计的秘密而已。但是,如果你的目的只是撰 写自己的代码,那么,源代码的作用无可替代。而且,你不需要付出任何代价,尽管用吧 好了,最重要的是,在其中寻找快乐吧。 H/BOOKS 第②2章 从内核出发 在这一章,我们将介绍 Linux内核的一些基本常识:从何处获取源码,如何编译它,又如何 安装新内核。那么,让我们考察一下内核程序与用户空间程序的差异,以及内核中所使用的通 用编程结构。虽然内核在很多方面有其独特性,但从现在来看,它和其他大型软件项目并无多 大差别 2.1获取内核源码 登录Linux内核官方网站http://www.kernel.org可以随时获取当前版本的Linux源代码,可 以是完整的压缩形式(使用tar命令创建的一个压缩文件),也可以是增量补丁形式 除特殊情况下需要 Linux源码的旧版本外,一般都希望拥有最新的代码。 kernel.org是源码 的库存之处,那些领导潮流的内核开发者所发布的增量补丁也放在这里。 2.1.1使用Git 在过去的几年中, Linus和他领导的内核开发者们开始使用一个新版本的控制系统来管理 Linux内核源代码。 Linus创造的这个系统称为〔it。与CSV这样的传统的版本控制系统不同 Git是分布式的,它的用法和工作流程对许多开发者来说都很陌生。我强烈建议使用Git来下载 和管理 Linux内核源代码 你可以使用Git来获取最新提交到 Linus版本树的一个副本 s git clone git: //git kernel. org/pub/scm/linux/kernel/git/torvalds/linux-26git 当下载代码后,你可以更新你的分支到 Linus的最新分支: git pull 有了这两个命令,就可以获取并随时保持与内核官方的代码树一致。要提交和管理自己的修 改,请看第20章。关于Git的全面讨论已经超出了本书的范围,许多在线资源都提供了有效的 指导。 2.1.2安装内核源代码 内核压缩以 GNU Zip(gzip)和bzip2两种形式发布。bzip2是默认和首选形式,因为它在压 缩上比gzp更有优势。以bzip2形式发布的 Linux内核叫做 linux-x.y.z.tar.bz2,这里x.y.z是内核 源码的具体版本。下载了源代码之后,就可以轻而易举地对其解压。如果压缩形式是bzip2,则

...展开详情
试读 34P Linux内核设计与实现(原书第3版)-第1~3章
立即下载 低至0.43元/次 身份认证VIP会员低至7折
抢沙发
一个资源只可评论一次,评论内容不能少于5个字
  • 领英

    绑定领英第三方账户获取
关注 私信 TA的资源
上传资源赚积分or赚钱
    最新推荐
    Linux内核设计与实现(原书第3版)-第1~3章 10积分/C币 立即下载
    1/34
    Linux内核设计与实现(原书第3版)-第1~3章第1页
    Linux内核设计与实现(原书第3版)-第1~3章第2页
    Linux内核设计与实现(原书第3版)-第1~3章第3页
    Linux内核设计与实现(原书第3版)-第1~3章第4页
    Linux内核设计与实现(原书第3版)-第1~3章第5页
    Linux内核设计与实现(原书第3版)-第1~3章第6页
    Linux内核设计与实现(原书第3版)-第1~3章第7页

    试读结束, 可继续读4页

    10积分/C币 立即下载 >