📄 1152.html
字号:
<br>
Version 0.8-3 <br>
<br>
David A Rusling <br>
<br>
david.rusling@arm.com <br>
<br>
<br>
-------------------------------------------------------------------------------- <br>
前言 <br>
Linux是互连网上的独特现象。虽然它是由学生的业余爱好发展而来,但是现在它已经成为最为流行的免费操作系统。对很多人来说,Linux是一个谜。免费的东西怎么会变得如此有价值?在个由少数软件公司统治的世界,由一帮HACKER们编写的东西是怎样与那些公司的产品竞争的? 这些软件是如何分发给分布在世界各个角落,希望得到稳定产品的人们的?事实上Linux的确稳定而富有竞争力。许多大学与研究机构都使用Linux完成他们的日常计算任务。人们在家用PC上使用Linux,许多公司也在使用它--尽管他们并不总是乐意承认这点。Linux主要用来浏览WEB,管理WEB站点,撰写与发送EMAIL,以及玩游戏。Linux绝对不是玩具而是具有专业水平的操作系统,它的爱好者遍及世界。 <br>
<br>
Linux的源头要追溯到最古老的UNIX。1969年,Bell实验室的Ken Thompson开始利用一台闲置的 PDP-7计算机开发了一种多用户,多任务操作系统。很快,Dennis Richie加入了这个项目,在他们共同努力下诞生了最早的UNIX。Richie受一个更早的项目——MULTICS的启发,将此操作系统命名为Unix。早期UNIX是用汇编语言编写的,但其第三个版本用一种崭新的编程语言C重新设计了。C是Richie设计出来并用于编写操作系统的程序语言。通过这次重新编写,Unix得以移植到更为强大的 DEC PDP-11/45与11/70计算机上运行。后来发生的一切,正如他们所说,已经成为历史。Unix从实验室走出来并成为了操作系统的主流,现在几乎每个主要的计算机厂商都有其自有版本的Unix. <br>
<br>
Linux起源于一个学生的简单需求。Linus Torvalds,Linux的作者与主要维护者,在其上大学时所买得起的唯一软件是Minix. Minix是一个类似Unix,被广泛用来辅助教学的简单操作系统。Linus 对Minix不是很满意,于是决定自己编写软件。他以学生时代熟悉的Unix作为原型, 在一台Intel 386 PC上开始了他的工作。他的进展很快,受工作成绩的鼓舞,他将这项成果通过互连网与其他同学共享,主要用于学术领域。有人看到了这个软件并开始分发。每当出现新问题时,有人会立刻找到解决办法并加入其中,很快的, Linux成为了一个操作系统。值得注意的是Linux并没有包括Unix源码。它是按照公开的POSIX标准重新编写的。Linux大量使用了由麻省剑桥免费软件基金的GNU软件,同时Linux自身也是用它们构造而成。 <br>
<br>
许多人将Linux视作简单工具并将其放入CDROM中来分发。很多Linux使用者使用它来编写应用程序或者运行别人编写的应用程序。这些人热切的阅读HOWTO手册,当系统的一部分被正确的设置时,他们总是激动不已,失败时则沮丧气馁。只有少部分人敢于编写设备驱动程序并将核心的补丁提供给Linus Torvalds,Linus Torvalds从每个志愿者那里接收补充代码与对核心的修改代码。 <br>
<br>
这种情形听起来象非常混乱,但Linus进行了非常严格的质量控制并由他负责将所有的新代码加入核心。只有少部分人对Linux 核心贡献了源代码。 大多数Linux的使用者并不关心系统是如何工作,或者如何组合在一起的。这种情况令人惋惜,因为阅读Linux源代码提供了一个学习操作系统的绝好机会。这不仅仅因为它写得好,还因为它的源码是可以免费得到的。因为虽然作者们对其软件保留版权,但是在免费软件基金的GNU公开授权下源代码是可以自由分发的。第一眼看去,源码是非常复杂的。但是通过进一步观察你可以发现源码目录中包含有Kernel,mm以及net的目录, 不过要想知道这些目录中包含了那些代码以及代码是如何工作的就需要对Linux的总体结构与目标有较深入的理解。简而言之,这也是本书所希望达到的目标,为读者提供一个Linux如何工作清晰的印象。当你将文件从一个目录拷到另一个目录或者阅读电子邮件时,不妨在脑海中勾勒一下系统中正在发生什么事情,我还清楚的记得当我感到第一次认识到操作系统真的在工作时的兴奋。这种兴奋正是我想将它带给本书的读者的。 <br>
<br>
我第一次接触Linux在1994年下半年当我拜访Jim Paradis时,当时他正在致力于将Linux移植到Alpha AXP处理器系统上。从1984年开始,我曾经在DEC公司任职,主要工作是网络与通讯。1992年我开始为新成立的Digital Semiconductor分部工作。此分部的任务是全面进入商用芯片市场并销售芯片,特别是Alpha AXP系列处理器以及DEC以外的Alpha AXP系统板。当首次听到Linux时我便立刻意识到了这是一个有趣的机会。Jim的狂热是鼓惑人心的,我也开始帮他一起工作。在工作中,我越来越喜欢这个操作系统及创造它的工程师团体。 <br>
<br>
Alpha AXP仅仅是Linux可以运行的多种平台中的一个。大多数Linux核心工作在基于Intel处理器 的系统上,但非Intel系统的Linux用户也越来越多。它们是Alpha AXP, ARM, MIPS, Sparc与Power PC。 虽然我可以根据上叙任何一种平台来编写本书的内容,但是我的技术知识与背景让我主要根据Alpha AXP处理器和ARM处理器来编写。这是本书有时使用非Intel硬件来描叙一些重要观点。值得注意的是,不管运行在哪种平台上,95%的Linux核心代码都是相同的。同样,本书95%的内容是关于Linux 内核的机器无关部分的讨论。 <br>
<br>
本书对读者的知识与经验没有任何要求。我相信对于某一事物的兴趣是鼓励自学的必要因素。不过对于计算机,或者PC和C程序语言的了解将有助于读者从有关材料中获益。 <br>
<br>
本书的组织 <br>
本书并不是特意一本Linux的内部手册。相反它是对操作系统的介绍,同时以Linux作为示例。书中每一章遵循“从共性到特性”的原则。它们将首先给出核心子系统的概叙,然后进行尽可能的详细描叙。 我不会用routine_X()调用routine_Y()来增加bar数据结构中foo域的值这种方式来描叙核心算法。 你自己可以通过阅读代码发现它。每当需要理解一段代码时,我总是将其数据结构画出来。这样我发现了许多相关的核心数据结构以及它们之间的关系。 每一章都是非常独立的,就象Linux核心子系统一样。当然有时它们还是有联系的,比如说,如果你没有理解虚拟内存工作原理就无法描叙进程。 硬件基本概念一章对现代PC做了简要介绍。操作系统必须与硬件系统紧密结合在一起协同工作。操作系统需要一些只能够由硬件提供的服务。为了全面理解Linux,你必须了解有关硬件的基础知识。 软件基本概念一章介绍了软件基本原理与C程序语言。讨论了建立Linux这样的操作系统的工具并且给出了操作系统的目标与功能的概叙。 内存管理这章描叙了Linux如何处理物理内存以及虚拟存储技术。 进程管理描叙了进程的概念以及Linux核心是如何创建、管理与删除系统中的进程。 进程间及进程与核心间通讯以协调它们的活动。Linux支持大量进程间通讯(IPC)机制。信号与管道是 其中的两种,Linux同时还支持系统V IPC机制。这些进程间通讯机制在IPC一章中描叙。 外部设备互连(PCI)标准已经成为PC上低价位高数传率的总线标准。PCI一章将描叙Linux核心是如何初始化并使用PCI总线及设备的。 中断及中断处理一章将着重于Linux核心对中断的处理。虽然处理中断有通用的机制与接口,但某些细节是与硬件及CPU体系结构相关的。 Linux的一个长处是其对现代PC的硬件设备强有力的支持。设备驱动程序一章将描叙Linux核心是如何控制系统中的物理设备。 文件系统一章描叙了Linux核心是如何维护它所支持的文件系统中的文件。同时还描叙了虚拟文件系统(VFS)及Linux核心的每种文件系统是如何得到支持。 网络与Linux几乎是同义的。在某种意义上Linux是WWW时代互连网的产物。其开发者通过Web来交换信息及代码。网络一章描叙了Linux是如何支持TCP/IP这些网络协议。 核心机制一章主要讨论能使Linux核心其他部分有效工作而由核心所提供的一些通用任务与机制。 动态模块一章描叙Linux核心是如何仅在需要时动态加载某些模块,比如文件系统。 处理器一章给出了目前Linux可以在其上运行的一些处理器的简要介绍。 资源一章则提供了有关Linux核心资源的有用信息。 <br>
<br>
Linux 核心--2.硬件基础 <br>
原著: David A Rusling 翻译: Banyan & fifa (2001-04-27 13:53:43) <br>
第一章 硬件基础 <br>
<br>
<br>
操作系统必须与基本硬件系统密切协作。它需要那些仅仅能够由硬件提供的服务。为了全面理解Linux操作系统,你必须要懂得一些有关硬件的知识。本章将对硬件:现代PC做一个简要的介绍。 当1975年一月的"Popular Electronics"杂志以Altair 8080的图片作为封面时,一场革命开始了。 家用电器爱好者能独立组装出来的Altair 8080,当时价格仅仅为397美圆。这种带有256字节内存的8080处理器还没有显示器与键盘,以今天的标准来看,它是微不足道的。它的创造者, Ed Roberts,发明了"personal computer"来描叙他的新发明。但现在PC这一术语已被用来称呼那些自己就可以携带的计算机。在这个定义上,非常强劲的计算机如Alpha AXP 也可称为PC。 狂热的HACKER们看到了Altair的巨大潜力,于是他们开始为它编写软件和设计硬件。对早期的先驱来说这意味者某种自由;一种从顽固的超级批处理主机中解放出来的自由。滚滚而来的财富让许多着迷于此(一台可以放在厨房餐桌上的计算机)的大学生纷纷退学。许多五花八门的硬件开始出现,软件 HACKER们忙着为这些新机器编写软件。有意思的是IBM首先坚定的进行现代PC的设计和制造并于1982 年推出产品。该产品的构造是:8080 CPU、64K字节主存、两个软盘驱动器以及25行80列的彩色CGA 显示器。虽然以现在观点看那些都不是多么先进的东西但当时销售情况却很好。紧接着,1983年,带有昂贵的10MB硬盘驱动器的IBM PC-XT出现了。在IBM PC体系结构成为事实上的标准不久之后,大量仿制者如COMPAQ公司出现了。由于这种事实标准的存在,多个硬件公司在这一快速增长的市场上进行了激烈竞争。 但用户却从低价中获益。许多早期PC中的结构特征还保留在现代PC系统中。比如Intel公司最先进的Pentium Pro处理器还保留着Intel 8086的寻址模式。当Linus Torvalds开始写Linux时,他选择了当时最广泛使用同时价格合理的Intel 80386 PC。 图1.1 典型的PC主板示意图。 从PC的外部来看,最引人注目的是机箱,键盘,鼠标以及显示器。在机箱前部有一些按钮,一个微型显示器显示着一些数字,此外还有一个软驱。今天的大多数机器还包含一个CD ROM,另外,如果想保护你的数据,还可以添加一个磁带机作为备份用。这些设备统称为外部设备。 尽管CPU是系统的总管,但是它仅仅是一个智能设备。所有的这些外设控制器都具有某种层度的智能,如IDE控制器。在PC内部,你可以看到一个包括CPU或者微处理器,主存和许多ISA或PCI外设控制器插槽的主板(图1.1)。有些控制器,如IDE磁盘控制器必须建立在系统板上。 <br>
<br>
<br>
<br>
<br>
图 1.1: 典型的PC主板. <br>
<br>
<br>
1.1 CPU <br>
CPU,或者微处理器,是计算机系统的核心。微处理器进行计算或者逻辑操作并且管理来自主存的指令并执行它。在计算机的早期时代,微处理器的功能部件使用的是分立元件(外型很大)。 这就是中央处理单元这一名词的由来。现代微处理器将部件结合到小型硅片上的集成电路中。在本书中CPU和微处理器及处理器有相同的意义。 微处理器的操作对象是二进制数据;数据由0和1组成。 1和0对应着电子开关的开路与断路状态。正如十进制的42表示有4个10和一个2一样,一个二进制数是一系列表示2的次幂的二进制数字组成。二进制0001对应十进制的1,二进制的0010对应十进制 的2,二进制的0011表示3,而0100对应4。十进制42的二进制表示为101010。但是在计算机程序中, 人们常用十进制来表示数而不是直接使用二进制。 在需要使用二进制数时,人们往往使用16进制数。如十进制数只能从0到9一样,16进制数可以从 0疏导15,其中10到15分别用字母A、B、C、D、E及F来表示。这样16进制的2A的十进制表示为42- 2*16+10=42。在C程序语言中,16进制数的前缀为"0x";16进制的2A写成0x2A。 微处理器可以执行如加、乘和除以及象"X是否比Y大"这种逻辑运算。 处理器的执行由外部时钟来监控。这个时钟称为系统时钟,它每隔相同的时间间隔就向CPU发送一个脉冲。在每个时钟脉冲上,处理器都会做一些工作。比如,处理器每个时钟脉冲上执行一条指令。处理器的速度一般以系统时钟的速率来描叙。一个100MHz的处理器每秒将接收100,000,000 个时钟滴答。但是用CPU的时钟频率来描叙CPU的工作能力是不正确的,因为它们执行的指令不相同。 然而,快速的时钟可以在某种程度上代表高性能的CPU。处理器执行的指令是非常简单的;例如"将内存X处的内容读入寄存器Y"。寄存器是微处理器的内部存储部件,用来存储数据并对数据执行某些指令。有些指令有可能使处理器停止当前的工作而跳转到内存中另外一条指令执行。现代微处理器的紧凑设计使得它有可能每秒执行上百万甚至亿条指令。 指令执行前必须从内存中取出来。指令自身要使用的数据也必须从内存中取出来并放置在适当的地方。 微处理器中寄存器的大小、数量以及类型都取决于微处理器的类型。Intel 80486处理器和Alpha AXP 有迥然不同的寄存器,最明显的区别在于Intel 寄存器为32位而Alpha AXP为64位。一般来说,任何处理器都有许多通用寄存器和少量专用寄存器。许多微处理器有以下几种特定的寄存器。 <br>
<br>
程序计数器(PC) <br>
此寄存器包含下条指令执行的地址。每当取回一条指令时,PC的内容将自动增加。 <br>
堆栈指针(SP) <br>
微处理器经常需要访问存储临时数据的外部RAM。堆栈是一种便捷的存放临时数据的方法,处理器提供了特殊指令来将数值压入堆栈然后将其从堆栈中弹出。 堆栈以后进先出(LIFO)的方式工作。换句话说,如果你压入两个值X和Y,然后执行弹栈操作,你将取到Y的值。 有些处理器的堆栈从内存顶部向下增长而有些相反。但有的处理器同时支持这两种方式,如ARM。 <br>
<br>
处理机状态字(PS) <br>
指令的执行将得到执行结果;比如"寄存器X中的内容要大于寄存器Y中的内容?"将得到正确或错误作为结果。PS寄存器包含着这些信息及有关处理器当前状态的其他信息。例如大多数处理器至少有两种执行方式,核心(或管态)与用户方式。PS寄存器包含表示当前执行方式的信息。 <br>
<br>
1.2 内存 <br>
所有计算机系统都有一个由不同速度与大小的存储器组成的层次结构。最快的的存储器是高速缓存,它被用来暂存主存中的内容。这种存储器速度非常快但非常昂贵,大多数处理器都有少量的片上高速缓存或者将其放在主板上。有些处理器的高速缓存既包含数据也包含指令,但有些将其分成两部分。 Alpha AXP处理器有两个内部高速缓存,一个用来缓存数据(D-Cache)而另一个用来缓存指令(I- Cache)。而外部高速缓存(B-Cache)将两者混合。这样,相对外部高速缓存存储器,主存的速度非常慢。 高速缓存与主存中的内容必须保持一致。换句话说,对应于地址空间的同一个位置,如果该位置的数据被缓存入高速缓存,则其内容必须和主存中的一致。保证高速缓存一致性的工作由硬件和操作系统共同分担。 这就是在系统中硬件和软件必须紧密协作的原因。 <br>
<br>
1.3 总线 <br>
主板上分立的部件通过称为总线的线路连接在一起。系统总线的功能在逻辑上被划分为三部分: 地址总线、数据总线和控制总线。地址总线为数据传输指明内存位置(地址)。数据总线包含传输的数据。数据总线是双向的;它允许数据读入CPU也支持从CPU读出来。控制总线则包含几条表示路由分时和系统的控制信号。当然还有其他一些总线存在,例如ISA和PCI总线是将外设连接到系统的常用方式。 <br>
<br>
1.4 控制器与外设 <br>
外设是一些物理设备,比如说图象卡或者磁盘,它们受控于位于主板或者主板上插槽中的控制芯片。 IDE磁盘被IDE控制器芯片控制而SCSI磁盘由SCSI磁盘控制器芯片控制。这些控制器通过各种总线连接到CPU上或相互间互连。目前制造的大多数系统使用PCI和ISA总线来连接主要系统部件。控制器是一些类似CPU的处理器,它们可以看做CPU的智能帮手。CPU则是系统的总控。 虽然所有这些控制器互不相同,但是它们的寄存器的功能类似。运行在CPU上的软件必须能读出或者写入这些控制寄存器。其中有一个寄存器可能包含指示错误的状态码。另一个则用于控制目的,用来改变控制器的运行模式。在总线上的每个控制器可以被CPU所单独寻址,这是软件设备驱动程序能写入寄存器并能控制这些控制器的原因。 <br>
<br>
1.5 地址空间 <br>
系统总线将CPU与主存连接在一起并且和连接CPU与系统硬件外设的总线隔离开。一般来说,硬件外设存在的主存空间叫I/O空间。I/O空间还可以进一步细分,但这里我们不再深究。CPU既可以访问系统内存空间又可以访问I/O空间内存,而控制器自身只能在CPU协助下间接的访问系统内存。从设备的角度来看,比如说软盘控制器,它只能看到在ISA总线上的控制寄存器而不是系统内存。典型的CPU使用不同指令来访问内存与I/O空间。例如,可能有一条指令"将I/O地址0x3F0的内容读入到寄存器X"。这正是CPU控制系统硬件设备的方式:通过读写I/O地址空间上的外设寄存器。在I/O空间中通用外设(IDE控制器、串行口、软盘控制器等等)上的寄存器经过多年的PC体系结构发展基本保持不变。I/O地址空间0x3f0是串行口(COM1)的控制寄存器之一。 有时控制器需要直接从系统主存中读写大量数据。例如当用户将数据写入硬盘时。在这种情况 下,直接内存访问(DMA)控制器将用来允许硬件外设直接访问系统主存,不过这将处于CPU的严格监控下。 <br>
<br>
1.6 时钟 <br>
所有的操作系统都必须准确的得到当前时间,所以现代PC包含一个特殊的外设称为实时时钟(RTC)。它提供了 两种服务:可靠的日期和时间以及精确的时间间隔。RTC有其自身的电池这样即使PC掉电时它照样可以工作,这就是PC总是"知道"正确时间和日期的原因。而时间间隔定时器使得操作系统能进行准确的调度工作。 <br>
<br>
<br>
<br>
Linux 核心--3.软件基础 <br>
原著: David A Rusling 翻译: Banyan & fifa (2001-04-27 13:54:15) <br>
<br>
第二章 软件基础 <br>
<br>
程序是执行某个特定任务的计算机指令集合。程序可以用多种程序语言来编写:从低级计算机语言-汇编语言到高级的、与机器本身无关的语言入C程序语言。操作系统是一个允许用户运行如电子表格或者字处理软件等应用程序的特殊程序。本章将介绍程序设计的基本原则,同时给出操作系统设计目标与功能的概述。 <br>
<br>
<br>
2.1 计算机编程语言 <br>
2.1.1 汇编语言 <br>
那些CPU从主存读取出来执行的指令对人类来说是根本不可理解的。它们是告诉计算机如何准确动作的机器代码。在Intel 80486指令中16进制数0x89E5表示将ESP寄存器的内容拷入EBP寄存器。为最早的计算机设计的工具之一就是汇编器,它可以将人们可以理解的源文件汇编成机器代码。汇编语言需要显式的操作寄存器和数据,并且与特定处理器相关。比如说Intel X86微处理器的汇编语言与Alpha AXP微处理器的汇编语言决然不同。以下是一段Alpha AXP汇编指令程序: <br>
<br>
ldr r16, (r15) ; Line 1 <br>
ldr r17, 4(r15) ; Line 2 <br>
beq r16,r17,100 ; Line 3 <br>
str r17, (r15) ; Line 4 <br>
100: ; Line 5 <br>
<br>
<br>
第一行语句将寄存器15所指示的地址中的值加载到寄存器16中。接下来将邻接单元内容加载到寄存器17中。 第三行语句比较寄存器16和寄存器17中的值,如果相等则跳转到标号100处,否则继续执行第四行语句:将 寄存器17的内容存入内存中。如果寄存器中值相等则无须保存。汇编级程序一般冗长并且很难编写,同时还容易出错。 Linux核心中只有很少一部分是用汇编语言编写,并且这些都是为了提高效率或者是需要兼容不同的CPU。 <br>
<br>
<br>
2.1.2 C编程语言和编译器 <br>
用汇编语言编写程序是一件困难且耗时的工作。同时还容易出错并且程序不可移植:只能在某一特定处理器 家族上运行。而用C语言这样的与具体机器无关的语言就要好得多。C程序语言允许用它所提供的逻辑算法来 描叙程序同时它提供编译器工具将C程序转换成汇编语言并最终产生机器相关代码。好的编译器能产生和汇编语言程序相接近的效率。Linux内核中大部分用C语言来编写,以下是一段C语言片段: <br>
<br>
if (x != y) <br>
x = y ; <br>
<br>
它所执行的任务和汇编语言代码示例中相同。如果变量X的值和变量Y的不相同则将Y的内容赋予X。C代码被 组织成子程序,单独执行某一任务。子程序可以返回由C支持的任何数据类型的值。较庞大的程序如Linux 核心由许多单独的C源代码模块组成,每个模块有其自身的子程序与数据结构。这些C源代码模块将相关函数组合起来完成如文件处理等功能。 C支持许多类型的变量,变量是一个通过符号名称引用的内存位置。在以上的例子中,X和Y都是内存中的位置。程序员并不关心变量放在什么地方,这些工作由连接程序来完成。有些变量包含不同类型的数据,整数和浮点数,以及指针。 指针是那些包含其他数据内存位置或者地址的变量。假设有变量X,位于内存地址0x80010000处。你可以使用指针变量px来指向X,则px的值为0x80010000。 C语言允许相关变量组合起来形成数据结构,例如: <br>
<br>
struct { <br>
int i ; <br>
char b ; <br>
} my_struct ; <br>
<br>
这是一个叫做my_struct的结构,它包含两个元素,一个是32位的整数i,另外一个是8位的字符b。 <br>
<br>
<br>
2.1.3 连接程序 <br>
连接程序是一个将几个目标模块和库过程连接起来形成单一程序的应用。目标模块是从汇编器或者编译器中产生的机器代码,它包含可执行代码和数据,模块结合在一起形成程序。例如一个模块可能包含程序中所有的数据库函数而另一个主要处理命令行参数。连接程序修改目标模块之间的引用关系,使得在某一模块中引用的数据或者子程序的确存在于其他模块中。Linux核心是由许多目标模块连接形成的庞大程序。 <br>
<br>
<br>
2.2 操作系统概念 <br>
如果没有软件,计算机只不过是一堆发热的电子器件。如果将硬件比做计算机的心脏则软件就是它的灵魂。操作系统是一组系统程序的集合,它提供给用户运行应用软件的功能。操作系统对系统硬件进行抽象,它提供给系统用户一台虚拟的机器。大多数PC可以运行一种或者多种操作系统,每个操作系统都有不同的外观。Linux由许多独立的功能段组成。比如Linux内核,如果没有库函数和外壳程序,内核是没有什么用的。 为了理解操作系统到底是什么,思考一下当你敲入一个简单命令时,系统中发生了什么: <br>
<br>
<br>
$ ls <br>
Mail c images perl <br>
docs tcl <br>
$ <br>
<br>
<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -