嵌入式操作系统_第1页
嵌入式操作系统_第2页
嵌入式操作系统_第3页
嵌入式操作系统_第4页
嵌入式操作系统_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

嵌入式操作系统第一页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统22.1Linux及其应用Linux操作系统是UNIX操作系统的一种克隆系统。它诞生于1991年的10月5日(这是第一次正式向外公布的时间)。此后借助于因特网,经过全世界各地计算机爱好者的共同努力,现已成为当今世界上使用最多的一种UNIX类操作系统,并且使用人数还在迅猛增长。2.1.1Linux与UNIX和GNU2.1.2Linux的特点2.1.3Linux的发展及应用第二页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统3Linux与UNIX和GNUUNIX操作系统是美国贝尔实验室的Ken.Thompson和DennisRitchie于1969年夏在DECPDP-7小型计算机上开发的一个分时操作系统。KenThompson在1969年夏天利用一个月的时间开发了UNIX操作系统的原型。后经DennisRitchie于1972年用移植性很强的C语言进行了改写,使得UNIX系统在大专院校得到了推广。MINIX系统是由AndrewS.Tanenbaum(AST)于1987年开发的,主要用于学生学习操作系统原理。AST工作在荷兰Amsterdam的Vrije大学,并从事数学与计算机科学系统研究,是ACM和IEEE的资深会员(全世界也只有很少人是两会的资深会员)。GNU计划和自由软件基金会FSF(theFreeSoftwareFoundation)是由RichardM.Stallman于1984年一手创办的,旨在开发一个类似UNIX,并且是自由软件的完整操作系统:GNU系统(GNU是“GNU’sNotUNIX”的递归缩写,它的发音为“gun-NEW”)。各种使用Linux作为核心的GNU操作系统正在被广泛地使用。虽然这些系统通常被称为“Linux”,但是Stallman认为,以严格意义上讲,它们应该被称为GNU/Linux系统。到20世纪90年代初,GNU项目已经开发出许多高质量的免费软件,其中包括有名的emacs编辑系统、bashshell程序、gcc系列编译程序、gdb调试程序,等等。这些软件为Linux操作系统的开发创造了一个合适的环境,这也是Linux能够诞生的基础之一,以至于目前许多人都将Linux操作系统称为“GNU/Linux”操作系统。第三页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统4POSIX(PortableOperatingSystemInterfaceforComputingSystems)是由IEEE和ISO/IEC开发的一组标准。该标准是基于现有UNIX的实践经验,描述了操作系统的调用服务接口。用于保证编制的应用程序可以在源代码一级上、在多种操作系统上移植和运行。它是在1980年一个UNIX用户组(usr/group)的早期工作基础上完成的。20世纪90年代初,POSIX标准的制定处于最后投票敲定的时候,此时也正是Linux刚刚起步的时候,这个UNIX标准为Linux提供了极为重要的信息,使得Linux能够在标准的指导下进行开发,并能够与绝大多数UNIX操作系统兼容。通过上述说明,我们可以对上述Linux的5大支柱归纳如下:

UNIX操作系统——Linux就是UNIX的一种克隆系统。UNIX的重要性就不用多说了。

MINIX操作系统——MINIX操作系统也是UNIX的一种克隆系统,它于1987年由著名计算机教授AndrewS.Tanenbaum开发完成。由于MINIX系统的出现并且提供源代码(只能免费用于大学内),在全世界的大学中刮起了学习UNIX系统旋风。Linux刚开始就是参照MINIX系统于1991年才开始开发。

GNU计划——开发Linux操作系统,以及Linux上所用大多数软件基本上都出自GNU计划。Linux只是操作系统的一个内核,没有GNU软件环境(如bashshell),则Linux将寸步难行。

POSIX标准——该标准在推动Linux操作系统以后朝着正规路上发展起着重要的作用,是Linux前进的灯塔。

Internet——如果没有Internet网,没有遍布全世界的无数计算机黑客的无私奉献,那么Linux最多只能发展到0.13(0.95)版的水平第四页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统5Linux的特点1.开放性是指系统遵循世界标准规范,特别是遵循开放系统互联(OSI)国际标准。凡遵循国际标准所开发的硬件和软件,都能彼此兼容,可方便地实现互联。Linux采用GPL授权,除了把源代码公开以外,任何人都可以自由使用、修改、散布;而Linux核心本身采用模块化设计,让人很容易增减功能,由于Linux具有这样高的可伸缩性,所以可以调出最适合我们硬件平台的核心出来。2.多用户是指系统资源可以被不同用户各自拥有并使用,即每个用户对自己的资源有特定的权限,互不影响。Linux和UNIX都具有多用户的特性。3.多任务是现代计算机最主要的一个特点。它是指计算机同时执行多个程序,而且各个程序的运行互相独立。Linux系统调度每一个进程平等地访问微处理器。由于CPU的处理速度非常快,其结果是,启动的应用程序看起来好像在并行运行。4.稳定性强,Linux不属于任何一家公司,但它却拥有全世界愿意投入自由软件的开发人员。在全球各处都有无数的人参与Linux核心的改进、调试与测试,也正因此造就了稳定度高的Linux。所以,Linux虽不是商业的产物,但它的质量却不逊于商业产品。5.设备独立性,是指操作系统把所有外部设备统一当做文件来看待,只要安装它们的驱动程序,任何用户都可以像使用文件一样,操纵、使用这些设备,而不必知道它们的具体存在形式。另外,由于用户可以免费得到Linux的内核源代码,因此,用户可以修改内核源代码,以便适应新增加的外部设备。第五页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统66.提供了丰富的网络功能完善的内置网络是Linux的一大特点。Linux在通信和网络功能方面优于其他操作系统。Linux为用户提供了完善的、强大的网络功能,包括支持Internet、文件传输和远程访问。7.可靠的系统安全在Linux操作系统中采取了许多安全技术措施,包括对读、写进行权限控制、带保护的子系统、审计跟踪、核心授权等,这些措施为网络多用户环境中的用户提供了必要的安全保障。8.良好的可移植性可移植性是指将操作系统从一个平台转移到另一个平台,并使它仍然能按其自身的方式运行的能力。Linux一开始是基于Intel386机器设计的,但是随着网络的散布,加上有许多工程师致力于各式平台的移植,使得Linux可以在x86、MIPS、ARM/StrongARM、PowerPC、Motorola68k、HitachiSH3/SH4、Transmeta等平台上运行。这些平台几乎覆盖了所有嵌入式系统的CPU种类,这样,在硬件平台设计时,使得可以考虑的CPU种类增加了不少。9.应用软件多自由软件世界里有个很大的特点就是软件多,授权几乎都是采用GPL方式,大家都可以自由参考与使用,但是因为这些软件多半是由设计者利用空余时间开发的,不以赢利为目的,所以并不能担保这些软件完全没有问题。尽管如此,仍有许多优秀软件出现,例如,大家熟知的KDE与GNOME便是很好的证明。第六页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统7Linux的发展及应用1991年10月5日,LinusTorvalds在新闻组发布了大约有1万行代码的Linuxv0.01版本。1992年,大约有1000人在使用Linux,基本上都属于真正意义上的黑客。1993年,大约有100余名程序员参与Linux内核代码编写/修改工作,其中核心组由5人组成,此时Linux0.99的代码大约有十万行,用户大约有10万个左右。1994年3月,Linux1.0发布,代码量为17万行,正式采用GPL协议。Linux的代码中充实了对不同硬件系统的支持,大大提高了跨平台移植性。1995年,Linux可在Intel、Digital,以及SunSPARC处理器上运行了,用户量也超过了50万,相关介绍Linux的LinuxJournal杂志的发行也超过10万册。1996年6月,Linux2.0内核发布,此内核大约有40万行代码,并可以支持多个处理器。此时的Linux已经进入了实用阶段,全球大约有350万人使用。1997年夏,好莱坞影片《泰坦尼克号》在制作特效中使用的160台Alpha图形工作站中,有105台采用了Linux操作系统。1998年是Linux迅猛发展的一年。RedHat5.0获得了InfoWorld的操作系统奖项。4月,Mozilla代码发布,成为Linux图形界面上的王牌浏览器。王牌搜索引擎“Google”现身,采用的也是Linux服务器。Mysql数据库充分得到发展。12月,IBM发布了适用于Linux的文件系统AFS3.5,以及JikesJava编辑器和SecureMailer及DB2测试版,IBM的此番行为,可以看做是与Linux的第一次亲密接触。迫于Windows和Linux的压力,Sun逐渐开放了Java协议,并且在UltraSparc上支持Linux操作系统。由此可见,1998年可以说是Linux与商业接触的一年。第七页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统81999年,IBM宣布与Redhat公司建立伙伴关系,以确保Redhat在IBM机器上正确运行。3月,第一届LinuxWorld大会的召开,象征Linux时代的来临。IBM、Compaq和Novell宣布投资Redhat公司,以前一直对Linux持否定态度的Oracle公司也宣布投资。5月,SGI公司宣布向Linux移植其先进的XFS文件系统。7月,IBM启动对Linux的支持服务,并发布了LinuxDB2。2000年初始,Sun公司在Linux的压力下宣布Solaris8降低售价。事实上,Linux对Sun造成的冲击远比对Windows来得更大。2月,RedHat发布了嵌入式Linux的开发环境,Linux在嵌入式行业的潜力逐渐被发掘出来。2001年Oracle宣布在OTN上的所有会员都可免费索取Oracle9i的Linux版本。IBM则决定投入10亿美元扩大Linux系统的应用。到了5月,微软公开反对“GPL”,此举引起了一场大规模的论战。8月,红色代码爆发,引得许多站点纷纷从Windows操作系统转向Linux操作系统。12月,RedHat为IBMs/390大型计算机提供了Linux解决方案。2002年是Linux企业化的一年。2月,微软公司迫于各州政府的压力,宣布扩大公开代码行动,这是Linux开源带来的深刻影响的结果。3月,内核开发者宣布新的Linux系统支持64位的计算机。2003年1月,NEC宣布将在其手机中使用Linux操作系统,代表着Linux成功进军手机领域。2004年6月的统计报告显示在世界500强超级计算机系统中,使用Linux操作系统的已经占到了280席,抢占了原本属于各种UNIX的份额。9月HP开始网罗Linux内核代码人员,以影响新版本的内核朝对HP有利的方式发展,而IBM则准备推出OpenPower服务器,仅运行Linux系统。第八页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统9Linux的应用和优势(以银行为例)银行业是中国各行业中开展信息化建设最早的行业之一,其信息化建设投入力度大,信息化水平高,在各行业的IT应用和系统建设中走在前列。(1)银行业的数据量大且集中决定了其对主机、存储设备、网络设备等硬件设备需求很大;同时对存储管理、数据仓库、网络管理、网络安全、CRM等方面的软件需求也不小。正由于银行业的数据量大且集中,因此金融安全问题也越发突出。Linux的高可靠性和安全性是它在这一行业中应用的有力保障。(2)对银行业而言,成本因素在整体经济环境欠佳的今天显得尤其重要。选择Linux的动力很大程度上来自于各个企业公司预算的减少。(3)Linux系统所具有的优良集群特性也是吸引更多客户的原因。Linux集群系统能够让客户相对落后的PⅡ或PⅢ计算机变成可以处理复杂任务的超级计算机系统。这对客户来说是非常有吸引力的。(4)北京市商业银行综合业务系统建设采用了基于IBMServeri系列服务器的Linux解决方案。该解决方案从整体上减少了总拥有成本,并且减少了系统管理的复杂性,实现了对人员、财政及信息技术的有效管理,同时还提高了服务器管理能力。(5)再以印度工业开发银行(IDBI)为例。他们自1995年开始使用Linux系统从事关键的电话银行、资产追踪及人力资源管理等业务,IDBI因此节省的IT预算达到70%。(6)如今有越来越多的商业公司采用Linux作为操作系统,例如,科学工作者使用Linux来进行分布式计算,ISP使用Linux配置Intranet服务器、电话拨号服务器等网络服务器,CERN(西欧核子中心)采用Linux做物理数据处理。第九页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统102.2Linux内核由于的源代码是完全公开的,任何人只要遵循GPL,就可以对内核加以修改并发布给他人使用。因此,在广大编程人员的支持下,Linux的内核版本不断更新,新的内核修改了旧内核的缺陷,并增加了许多新的特性。用户如果想在自己的系统中使用这些新的特性,或想根据自己的系统量身定制更高效、更稳定可靠的内核,只需要重新编译内核。当内核的编译工作完成之后,会生成一个可执行的二进制文件,该二进制文件放入嵌入式系统的ROM中,可以完成系统的上电、复位自动运行。2.2.1Linux的内核特征2.2.2进程管理2.2.3内存管理2.2.4文件系统管理2.2.5设备管理2.2.6进程间通信机制第十页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统11Linux的内核特征内核是操作系统的内部核心程序,它向外部提供了对计算机设备的核心管理调用。操作系统的代码分为以下两部分,内核所在的地址空间称为内核空间,外部管理程序与用户进程所占据的地址空间称为外部空间(用户空间)。通常,一个程序会跨越两个空间。当执行到内核空间的一段代码时,称程序处于核心态;而当程序执行到外部空间代码时,称程序处于用户态。单一内核(MonolithicKernel)曾经是操作系统的主流,它是指操作系统中所有的系统相关功能都被封装在内核中。它们与外部程序处在不同的内存地址空间中,并通过各种方式防止外部程序直接访问内核中的数据结构。程序只有通过一套称作系统调用(SystemCall)的界面访问内核结构。近些年来,微内核(MicroKernel)结构逐渐流行起来,成为操作系统的主要潮流。在微内核结构中,操作系统的内核只需要提供最基本、最核心的一部分操作(例如,创建和删除任务、内存管理、中断管理等)即可,而其他管理程序(如文件系统、网络协议栈等)则尽可能放在内核以外。这些外部程序可以独立运行,并对外部用户程序提供操作系统服务,服务之间使用进程间通信机制(IPC)进行交互。如同面向对象程序设计带来的好处一样,微内核使操作系统内部结构变得简单清晰。在内核以外的外部程序分别独立运行,其间并不互相关联。这样,可以对这些程序分别进行维护和拆装,只要遵循已经规定好的界面,就不会对其他程序有任何干扰。这使得程序代码在维护上十分方便,体现了面向对象式软件的结构特征。第十一页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统12微内核的结构也存在着不足之处。首先,程序代码之间的相互隔离,使得整个系统丧失了许多优化的机会。其次,部分资源浪费在外部进程之间的通信上,这样,微内核结构在效率上必然低于传统的单一内核结构,这些效率损失将作为结构精简的代价。总体上说,在当前的硬件条件下,微内核在效率上的损失小于其在结构上获得的收益,故而选取微内核成为操作系统的一大潮流。然而,Linux系统恰恰使用了单一内核结构。这是由于Linux是一个实用主义的操作系统。LinusTorvalds将代码执行效率作为自己操作系统的第一要务。在这样的发展过程中,参与Linux系统开发的程序员大多数为世界各地的黑客们。比起结构的清晰,他们更加注重功能的强大和高效率的代码。于是,他们将大量的精力花在优化代码上,而这样的全局性优化必然以损失结构精练作为代价,导致Linux中的每个部件都不能被轻易拆出,否则,必然破坏整体效率。虽然Linux是一个单一内核操作系统,但它与传统的单一内核UNIX操作系统不同。在普通的单一内核系统中,所有内核代码都是被静态编译连入的。而在Linux中,可以动态装入和卸载内核中的部分代码。Linux中将这样的代码段称为模块(Module),并对模块给予了强有力的支持。在Linux中,可以在需要时自动装入和卸载模块。Linux的内核为非抢占式的(Non-preemptive)。这就是说,Linux并不能通过改变优先权来影响内核当前的执行流程。Linux并不是一个“硬”实时操作系统。Linux操作系统的内核稳定而高效,以独占的方式执行最底层任务,来保证其他程序的正常运行。它是整个操作系统的核心,具有独特的性质。第十二页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统13进程管理进程是运行于自己的虚拟地址空间的一个程序。可以说,任何在Linux系统下运行的都是进程。Linux系统中包括下面几种类型的进程。

交互进程:该进程是由shell控制和运行的。它既可以在前台运行,也可以在后台运行。

批处理进程:该进程不属于某个终端,被提交到一个队列中以便顺序执行。

守护进程:该进程只有在需要时才被唤起在后台运行。它一般在Linux启动时开始执行。进程是动态的,在处理器执行机器代码时进程一直在变化。进程不但包括程序的指令和数据,而且包括程序计数器和CPU的所有寄存器,以及存储临时数据的进程堆栈。由此可见,正在执行的进程包括处理器当前的一切活动。Linux是一个多进程的操作系统,每个进程都有自己的权限和任务,某一进程的失败一般不会导致其他进程的失败,进程之间可以通过由内核控制的机制相互通讯。在进程的整个运行期间,它将会用到各种系统资源,会用到CPU运行它的指令,需要物理内存保存它的数据。它可能打开和使用各种文件,直接或间接地使用系统中的各种物理设备。Linux系统内核必须了解进程本身的情况和进程所用到的各种资源,以便在多个进程之间合理地分配系统资源。系统中最为宝贵的资源是CPU,因为在一般情况下,一个系统只有一个CPU。Linux是一个多进程的操作系统,所以,其他的进程必须等到正在运行的进程空闲CPU后才能运行。当正在运行的进程等待其他的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其他正在等待的进程。内核中的调度算法决定将CPU分配给哪一个进程。第十三页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统14进程管理程序能够进行进程的创建、激活、运行、阻塞、再运行、释放,以及删除。进程管理程序执行下列操作:在多进程(或者任务、线程)系统中执行每一个进程,使得进程状态可以切换。进程的顺序经过以下这些状态:“创建”、“就绪或者激活”、“产生”(创建且激活)、“运行”、“阻塞”、“再运行”、“完成”,以及“完成”之后的“就绪”(当进程中存在无限循环时)。最后,释放或者删除(在长进程中,阻塞和再运行可以发生很多次)。进程管理程序实现以下功能:

使进程能够顺序执行或者在需要资源时发生阻塞,并使其在资源可用时继续运行。

为进行资源管理(包括CPU上的进程调度)实现了与资源管理程序的逻辑链接。

限制某些资源只在某些进程间共享。

按照系统的资源分配机制分配资源。

管理系统中的进程和资源。第十四页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统151.进程与线程现在的嵌入式操作系统几乎都被要求能够与个人计算机上的操作系统一样,提供多任务(Multitasking)功能。但是多数的嵌入式系统只有一个处理器,要完成这样的要求,操作系统必须为这些不同的任务分配执行时间,而这些任务就要轮流利用分配到的执行时间来完成工作。为了方便管理这些任务,嵌入式操作系统会分别以一个执行单位来看待一项工作或一个程序,这个执行单位在不同的嵌入式操作系统中会有不同的名称与意义,但是基本的思想都是为了让不同的程序共同分享、使用有限的硬件资源,然后让用户在使用系统时,好像可以“同时”执行多个应用程序。Linux采用所谓“继承”的方法来进行资源分配。每个新的进程都必须先从父进程(ParentProcess)中去继承一份系统资源,基本上就是子进程(ChildProcess)分配到另外一块独立的内存空间,然后从父进程的内存空间中把所有的数据完完全全拷贝过来,再通过参数的设置决定是否与父进程分享资源,并决定子进程属于重优先权值进程(HeavyWeightProcess)还是轻优先权值进程(LightWeightProcess)。轻优先权值进程在Linux里也称为线程。第十五页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统162.进程的状态不论采用何种方式,嵌入式操作系统必须管理多任务的执行与切换,因为某一时刻真正被CPU执行的任务只有一个,所以当同时存在许多不同的任务时,每个任务的状态都不相同。一个进程在其生存期内,可处于一组不同的状态下,称为进程状态。如图2.2所示。操作系统会以一个特殊的数据结构来代表一个进程。这个特殊的数据结构会记录一些重要的数据,通常被称为PCB(ProcessControlBlock)或TCB(TaskControlBlock)。它除了包含taskcontext(任务上下文)之外,还会记录句柄、优先级,以及一些进程的附属数据,这些数据提供了调度程序(Scheduler)调度时所需的全部信息。进程状态就保存在TCB的state字段中。内核程序通过任务向量表对进程进行管理,每个进程在向量表中占有一项。在Linux系统中,任务向量表项是一个task_struct任务结构指针(在Linux中task和process互用)。任务数据结构定义在头文件include/linux/sched.h中。这个数据结构也就是前面提到的TCB或PCB。当新的进程创建的时候,进程管理模块从系统内存中分配一个新的task_struct,并增加到task向量表中。为了更容易查找,用current指针指向当前运行的进程。当一个进程在执行时,CPU的所有寄存器中的值、进程的状态,以及堆栈中的内容被称为该进程的上下文。当内核需要切换(switch)至另一个进程时,它就需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够恢复到切换时的状态并执行下去。在Linux中,当前进程的上下文均保存在进程的任务数据结构中。第十六页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统17第十七页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统18

运行状态(TASK_RUNNING),当进程正在被CPU执行,或已经准备就绪随时可由调度程序执行时,称该进程处于运行状态(running)。进程可以在内核态运行,也可以在用户态运行。当系统资源已经可用时,进程就被唤醒而进入准备运行状态,该状态称为就绪态。这些状态在内核中表示方法相同,都被称为处于TASK_RUNNING状态。

可中断睡眠状态(TASK_INTERRUPTIBLE),当进程处于可中断等待状态时,系统不会调度该进程执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(运行状态)。

不可中断睡眠状态(TASK_UNINTERRUPTIBLE),不可中断睡眠状态与可中断睡眠状态类似。但处于该状态的进程只有被使用wake_up()函数明确唤醒时,才能转换到可运行的就绪状态。

暂停状态(TASK_STOPPED),当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态,正在调试的进程可以处在停止状态。

僵死状态(TASK_ZOMBIE),当进程已停止运行,但其父进程还没有询问其状态时,则称该进程处于僵死状态。只有当进程从“内核运行态”转移到“睡眠状态”时,内核才会进行进程切换操作。在内核态下运行的进程不能被其他进程抢占,而且一个进程不能改变另一个进程的状态。为了避免进程切换时造成内核数据错误,内核在执行临界区代码时会禁止一切中断。第十八页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统193.进程的创建进程的创建是指为创建的进程定义地址空间(存储器块),并为进程定义资源。Linux系统采用继承的方式创建进程。进程管理程序在创建进程时分配TCB,并对它进行管理。TCB是进程管理程序使用的进程描述符。其他OS单元可以在必要的时候查询进程的TCB。系统启动的时候运行在核心态,这时,只有一个进程:初始化进程。初始化进程是一个在处理器重启时执行存储器指令,然后调用OS的进程。处理器随后开始执行创建的所有进程。像所有其他进程一样,初始进程有一组用堆栈、寄存器等表示的机器状态。当系统中的其他进程创建和运行时,这些信息存在初始进程的task_struct数据结构中。在系统初始化结束的时候,初始进程启动一个核心线程(init)然后执行空闲循环,即什么也不做。也就是说,当处理器没有什么可以做的时候,调度程序会运行这个空闲的进程。这个空闲进程的task_struct是惟一一个不是动态分配而是在核心连接的时候静态定义的,为了不至于混淆,叫做init_task。init核心进程拥有进程标志符1,是系统的第一个真正的进程。它执行系统的一些初始化的设置(比如,打开系统控制器,安装根文件系统等),然后执行系统初始化程序。根据系统的不同,初始化程序可能是/etc/init,/bin/init或/sbin/init其中之一。init程序使用/etc/inittab作为脚本文件创建系统中的新进程,这些新进程自身可能创建新的进程。例如,getty进程可能会在用户试图登录的时候创建一个login的进程。系统中的所有进程都是init核心线程的后代。第十九页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统20新进程的创建是通过克隆旧的进程,或者说克隆当前的进程来实现的。一个新的任务是通过系统调用创建的(fork或clone),克隆发生在核心的核心态。在系统调用的最后,产生一个新的进程,等待调度程序选择它运行(在新进程的创建未完成之前,为了防止这个还未处理完成的新建进程被调度函数执行,应该将新进程状态置为不可中断的等待状态)。在系统的物理内存中为这个克隆进程的堆栈(用户和核心)分配一个或多个物理的页用于新的task_struct数据结构。一个进程标志符将会创建,它在系统的进程标志符组中是惟一的。新的task_struct进入task向量表中,旧的(当前的)进程的task_struct的内容拷贝到克隆的task_struct。克隆进程的时候,Linux允许两个进程共享资源而不是拥有不同的拷贝,包括进程的文件,信号处理和虚拟内存。共享这些资源的时候,它们相应的count字段相应增减,这样,Linux在两个进程都停止使用之前不会释放这些资源。例如,如果克隆的进程要共享虚拟内存,它的task_struct会包括一个指向原来进程的mm_struct指针,mm_struct的count域增加,表示当前共享它的进程。4.进程的调度Linux进程是抢占式的。被抢占的进程仍然处于TASK_RUNNING状态,只是暂时没有被CPU运行。进程的抢占发生在进程处于用户态执行阶段,在内核态执行时是不能被抢占的。为了能让进程有效地使用系统资源,又能使进程有较快的响应时间,Linux中采用基于优先级排队的调度策略。通常,核心会以分时(TimeSlicing)的观念让多任务共享CPU资源,即将CPU执行的时间分成一段段的,每个程序会利用分配到的时间来执行任务。每一段的执行时间到了,就必须轮换下一个任务执行。至于轮到哪一个任务来执行,必须由核心的调度程序来决定。第二十页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统21在所有的进程中,部分运行于用户态,部分运行于核心态。底层的硬件支持这些状态的方式各不相同,但是通常有一个安全机制从用户态转入核心态并转回来。用户态比核心态的权限低很多。每一次进程执行一个系统调用,它都从用户态切换到核心态并继续执行。这时,让核心执行这个进程。在Linux中,进程不是通过互相争夺成为当前运行的进程,因为它们无法停止正在运行的其他进程而执行自身。每一个进程在它必须等待一些系统事件的时候会放弃CPU。例如,一个进程可能不得不等待从一个文件中读取一个字符,这个等待发生在核心态的系统调用中,进程使用了库函数打开并读文件,库函数又执行系统调用从打开的文件中读入字节。这时,等候的进程会被挂起,另一个合适的进程将会被选择执行。由于进程经常调用系统调用,所以经常需要等待。由于即使进程执行到需要等待,也有可能会用去不均衡的CPU时间,所以Linux使用抢先式的调度。用这种方案,每一个进程允许运行少量一段时间,通常为200毫秒,当这段时间过去,选择另一个进程运行,原来的进程等待一段时间直到它又重新运行。这个时间段就叫做时间片。调度程序的任务就是选择当前可运行的进程中最值得运行的一个进程。一个可以运行的进程是一个只等待CPU的进程。Linux使用合理而简单的基于优先级的调度算法在系统当前的进程中进行选择。当它选择了准备运行的新进程,就保存当前进程的状态、与处理器相关的寄存器,以及其他需要保存的上下文信息到进程的task_struct数据结构中。然后恢复要运行的新的进程的状态(又和处理器相关),把系统的控制交给这个进程。第二十一页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统22为了公平地在系统中所有可以运行(runnable)的进程之间分配CPU时间,调度程序在每一个进程的task_struct结构中保存了以下信息(参见Linux核心源文件kernel/sched.c中的函数schedule())。

Policy进程的调度策略。Linux有两种类型的进程:普通和实时。实时进程比所有其他进程的优先级高。如果有一个实时的进程准备运行,那么它总是先被运行。实时进程有两种策略:循环或先进先出(roundrobinandfirstinfirstout)。在循环的调度策略下,每一个实时进程依次运行,而在先进先出的策略下,每一个可以运行的进程按照它在调度队列中的顺序运行,这个顺序不会改变。

Priority进程的调度优先级。也是指它允许运行时可以使用的时间量(jiffies)。可以通过系统调用或者renice命令来改变一个进程的优先级。

Rt_priorityLinux支持实时进程。这些进程比系统中其他非实时的进程拥有更高的优先级。这个域允许调度程序赋予每一个实时进程一个相对的优先级。实时进程的优先级可以用系统调用来修改。

Counter这是进程可以运行的时间量(jiffies)。进程启动的时候等于优先级(priority)的数值,每一个时钟周期递减1。调度程序从核心的多个地方运行。它可以在把当前进程放到等待队列之后运行,也可以在系统调用之后进程从核心态返回用户态之前运行。需要运行调度程序的另一个原因是系统时钟刚好把当前进程的计数器(counter)置成0。第二十二页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统23每一次运行调度程序会完成以下工作:

kernelwork运行bottomhalfhandler并处理系统的调度任务队列。

Currentpoccess在选择另一个进程之前处理当前进程。

如果当前进程的调度策略是循环则将它放到运行队列的最后。

如果任务是可中断的而且它上次调度的时候收到过一个信号,将它的状态变为RUNNING。

如果当前进程超时,将它的状态成为RUNNING。

如果当前进程的状态为RUNNING则保持此状态。

将不是RUNNING或者INTERRUPTIBLE的进程从运行队列中删除。这意味着当调度程序查找最值得运行的进程时不会考虑这样的进程。

ProcessSelection查看运行队列中的进程,查找最值得运行的进程。

SwapProcesses如果最值得运行的进程不是当前进程,当前进程必须被挂起,运行新的进程。一个进程运行时会使用系统的CPU、寄存器和物理内存。每一次它调用例程都通过寄存器或者堆栈传递参数、保存数值等。可见,当调度程序运行的时候,它是在当前进程的上下文中运行。它可能处于特权模式:核心态,但是它仍旧运行在当前进程的上下文中。当这个进程需要挂起时,它的所有机器状态,包括程序计数器(PC)和所有的处理器寄存器,必须存到进程的task_struct数据结构中。然后,加载新进程的所有机器状态。这种操作依赖于系统,不同CPU的实现方法也不相同,不过,通常都是通过一些硬件的帮助来实现。第二十三页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统24具体调度过程如下:schedule()函数首先扫描任务数组。通过比较每个就绪态(TASK_RUNNING)任务的运行时间递减计数counter的值来确定当前哪个进程运行的时间最少。哪一个任务的counter值大,就表示运行时间还不长,于是就选中该进程,并使用任务切换宏函数切换到该进程运行。如果此时所有处于TASK_RUNNING状态进程的时间片都已经用完,系统就会根据每个进程的优先权值priority,对系统中所有进程(包括正在睡眠的进程)重新计算每个任务需要运行的时间片值counter。计算的公式是:counter

counter/2

priority然后schedule()函数重新扫描任务数组中所有处于TASK_RUNNING的状态,重复上述过程,直到选择出一个进程为止。最后调用switch_to()执行实际的进程切换操作。执行实际进程切换的任务由switch_to()宏定义的一段汇编代码完成。在进行切换之前,switch_to()首先检查要切换到的进程是否就是当前进程,如果是,则什么也不做,直接退出。否则就把内核全局变量current置为新任务的指针,然后完成上下文的切换。第二十四页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统255.进程的终止当一个进程结束了运行或在半途终止了运行,那么内核就需要释放该进程所占用的系统资源。这包括进程运行时打开的文件、申请的内存等。当一个用户程序调用exit()系统调用时,则执行内核函数do_exit()。该函数会首先释放进程代码段和数据段占用的内存页面,关闭进程打开着的所有文件等。如果进程有子进程,则让init进程作为其所有子进程的父进程,然后把进程状态置为僵死状态TASK_ZOMBIE,并向其原父进程发送SIGCHLD信号,通知其某个子进程已经终止。最后do_exit()调用调度函数去执行其他进程。由此可见,在进程被终止时,它的任务数据结构仍然保留着,因为其父进程还需要使用其中的信息。子进程在执行期间,父进程通常使用wait()或waitpid()函数等待其某个子进程终止。当等待的子进程被终止并处于僵死状态时,父进程就会把子进程运行所使用的时间累加到自己进程中。最终释放已终止子进程任务数据结构所占用的内存页面,并置空子进程在任务数组中占用的指针项。第二十五页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统26内存管理内存管理(MemoryManagement)系统是操作系统中最为重要的部分,内存管理程序子系统负责控制进程对硬件内存资源的访问。这是通过硬件内存管理单元(MemoryManagementUnit,MMU)来完成的,该单元提供进程内存引用与计算机的物理内存之间的映射。内存管理程序子系统为每个进程都维护一个这样的映射关系,使得两个进程就可以访问同一个虚拟内存地址,而实际使用的却是不同的物理内存位置。此外,内存管理程序子系统支持交换,它把暂时不使用的内存页面移出内存,存放到永久性存储器(如硬盘存储器)中,这样,计算机就可以支持比物理内存要多的虚拟内存。内存管理程序提供以下一些功能:

大地址空间——用户程序使用的内存数量可以超过物理上实际所有的内存数量。

保护——进程的内存是私有的,不能被其他进程所读取和修改。而且,内存管理程序可以防止进程覆盖代码和只读数据。

内存映射——可以把一个文件映射到虚拟内存区域,并把该文件当做内存来访问。

对物理内存的公平访问——内存管理程序确保所有的进程都能公平地访问计算机的内存资源,这样可以确保理想的系统性能。

共享内存——内存管理程序允许进程共享它们内存的一部分。第二十六页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统27虚拟内存的抽象模型:当处理器执行一个程序时,它从内存中读取指令并解码执行。当执行这条指令时,处理器可能会需要在内存的某一个位置读取或存储数据。进程不管是读取指令还是存取数据都要访问内存。在一个虚拟内存系统中,所有程序涉及到的内存地址均为虚拟内存地址而不是机器的物理地址。处理器根据操作系统保存的一些信息将虚拟内存地址转换为物理地址。为了让这种转换更容易地进行,虚拟内存和物理内存都分为大小固定的块,叫做页面(Page)。每一个页面有一个惟一的页面号,叫做PFN(PageFrameNumber)。Linux在AlphaAXP系统上使用8K字节的页,而在Intelx86系统上使用4K字节的页。在这种分页方式下,一个虚拟内存地址由两部分组成:一部分是位移地址,另一部分是PFN。每当处理器遇到一个虚拟内存地址时,都将会分离出位移地址和PFN地址。然后再将PFN地址转换成物理地址,读取其中的位移地址。处理器利用页面表(PageTables)来完成上述的工作。图2.3所示是进程X和进程Y的虚拟内存示意图。两个进程分别有自己的页面表。这些页面表用来将进程的虚拟内存页映射到物理内存页中。可以看出,进程X的虚拟内存页0映射到了物理内存页1,进程Y的虚拟内存页1映射到了物理内存4。页面表的每个入口一般都包括以下的内容:有效标志——此标志用于标明页面表入口是否可以使用。物理页面号——页面表入口描述的物理页面号。存取控制信息——用来描述页面如何使用,例如,是否可写,是否包括可执行代码等第二十七页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统28第二十八页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统29处理器读取页面表时,使用虚拟内存页号作为页面表的位移,例如,虚拟内存页5是页面表的第6个元素。在将虚拟内存地址转换成物理内存地址时,处理器首先将虚拟内存地址分解为PFN和位移值。例如,在图2.3中,一个页面的大小是0x2000字节(十进制的8192),那么进程Y的一个虚拟内存地址0x2194将被分解成虚拟内存页号PFN为1和位移0x194。然后处理器使用PFN作为进程页面表的位移值来查找页面表的入口。如果该入口是有效入口,处理器则从中取出物理内存的页面号。如果入口是无效入口,处理器则产生一个页面错误给操作系统,并将控制权交给操作系统。假定此处是一个有效入口,则处理器取出物理页面号,并乘以物理页面的大小以便得到此物理页面在内存中的地址,最后加上位移值。再看上面的例子:进程Y的PFN为1,映射到物理内存页号为4,则此页从0x8000(40x2000)开始,再加上位移0x194,得到最终的物理地址为0x8194。第二十九页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统301.按需装入页面(DemandPaging)由于物理内存要比虚拟内存小很多,所以操作系统一定要十分有效地利用系统的物理内存。一种节约物理内存的方法是只将执行程序时正在使用的虚拟内存页面装入系统的物理页面中。当一个进程试图存取一个不在物理内存中的虚拟内存页面时,处理器将会产生一个页面错误给操作系统。如果发生页面错误的虚拟内存地址为无效的地址,说明处理器正在存取一个它不应该存取的地址。这时,有可能是应用程序出现了某一方面的错误,在这种情况下,操作系统将会中止进程的运行,以防止系统中的其他进程受到破坏。如果发生页面错误的虚拟内存地址为有效的地址,但此页面当前并不在物理内存中,则操作系统必须从硬盘中将正确的页面读到系统内存中。相对而言,由于读取硬盘要花费较长的时间,所以处理器必须等待,直到页面读取完毕。如果此时还有另外的进程等待运行,则操作系统将选择一个进程运行。从硬盘中读取的页面将被写入到一个空的物理内存页中,然后在进程的页面表中加入一个虚拟内存页面号入口,此时进程就可以重新运行了。Linux系统使用按需装入技术(DemandPaging)将可执行代码装入到进程的虚拟内存中。每当一个命令执行时,包括此命令的文件将被打开并映射到进程的虚拟内存中。此过程是通过修改描述进程内存映射的数据结构来实现的,通常被叫做内存映射(MemoryMapping)。但此时只有文件镜像的第一部分被装入系统的物理内存中,而镜像的其他部分还保留在硬盘中。当此镜像执行时,处理器将产生页面错误,Linux使用进程的内存映射表决定应该把镜像的哪一部分装入内存中执行。第三十页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统312.交换(Swapping)当一个进程需要把一个虚拟内存页面装入物理内存而又没有空闲时,操作系统必须废弃物理内存中的一个页面,为将要装入的虚拟内存页腾出空间。如果将要扔掉的物理内存页一直没有被改写过,则操作系统将不保存此内存页,而只是简单地将它扔掉。当再次需要此内存页时,再从文件镜像中装入。但是,如果此页面已经被修改过,操作系统就需要把页面的内容保存起来。这些页面称为“脏页面”(dirtypage)。当它们从内存中移走时,将会被保存到一种叫做交换文件的特殊文件中。Linux系统使用一种叫做“最近最少使用”的技术(LeastRecentlyUsed,LRU)来决定把哪一个页面从物理内存中移出。3.共享虚拟内存(SharedVirtualMemory)由于使用了虚拟内存,因此使几个进程之间的内存共享变得很容易。每个内存的存取都要通过页面表,而且每个内存都有自己的单独的页面表。如果希望两个进程共享一个物理内存页,只需将它们页面表入口中的物理内存号设置为相同的物理页面号即可,而且共享的物理页不必存在共享它的进程的虚拟内存空间的同一个地方。4.访问控制(AccessControl)页面表中还包括了访问控制信息。当处理器使用页面表将进程的虚拟地址映射到物理地址的时候,可以方便地使用存取控制信息来检查进程是否存取了它不该存取的信息。访问控制信息放在PTE(PageTableEntry)中,而且与具体处理器相关。第三十一页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统325.高速缓存(Caches)为了获得最大的系统效用,操作系统一般使用高速缓存来提高系统性能。Linux系统使用了以下几种涉及高速缓存的内存管理方法。

BufferCache:缓冲区高速缓存,其中包含了由块设备使用的数据缓冲区。

PageCache:页面高速缓存,用来加速磁盘中文件镜像和数据的存取。

SwapCache:交换文件,其中只保存那些被修改过的页面。

HardwareCache:硬件高速缓存,通常是在处理器中,它保存着页面表的入口。高速缓存的副作用在于Linux必须花大量时间和空间来维护这些高速缓存区,如果这些高速缓存区崩溃,系统也会崩溃。6.页的分配和回收(PageAllocationandDeallocation)系统在运行时会经常需要物理内存页。例如,当一个文件镜像从磁盘调入内存时,操作系统需要为它分配物理内存页。当程序执行完毕时,操作系统需要释放内存页。物理页的另一个用途是存储内核所需要的数据结构,例如,页面表。页面的分配和撤销机制,以及所涉及的数据结构对内存管理来说是至关重要的。系统中所有的物理内存页都包括在mem_map数据结构中,而mem_map是由mem_map_t结构组成的链表。mem_map_t在系统启动时初始化,每个mem_map_t结构都描述了系统中的一个物理页。第三十二页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统337.内存映射(MemoryMapping)当执行一个文件镜像时,可执行镜像的内容必须装到进程的虚拟地址空间。可执行镜像链接的共享库也是一样要装入虚拟内存空间。可执行文件并不是真正地装入物理内存空间,而只是简单地链接到进程的虚拟内存。然后,随着应用程序运行时的需要,可执行镜像才逐渐地装入到物理内存中。这种将一个文件的镜像和一个进程的虚拟内存地址空间连接起来的方法叫做内存映射。数据结构mm_struct代表每个进程的虚拟内存空间。它包含了正在执行的镜像的信息和一些指向vm_area_struct结构的指针,如图2.4所示。每个vm_area_struct结构都描述了进程的虚拟内存的起始和结束位置、进程的存取权限,以及与内存有关的一系列的操作。这些操作是Linux系统在处理虚拟内存时将要用到的。当一个可执行镜像映射到一个进程的虚拟内存地址时,操作系统将创建一系列的数据结构vm_area_struct,每一个vm_area_struct代表可执行镜像的一部分。Linux系统支持多种标准虚拟内存操作,创建vm_area_struct时,相应的虚拟内存操作就会与vm_area_struct链接起来。第三十三页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统34第三十四页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统35文件系统管理Linux在设计时就考虑到支持许多不同的物理设备,甚至就一种特定类型的设备而言,例如,硬盘驱动器,在不同的硬件厂商之间也会存在许多接口上的差异。除了Linux所支持的物理设备以外,Linux还支持大量的逻辑文件系统。正因为它能支持许多逻辑文件系统,所以Linux可以轻松地与其他操作系统进行互操作。Linux文件系统支持下列特性:

多个硬件设备——提供对许多不同的硬件设备的访问。

多个逻辑文件系统——支持许多不同的逻辑文件系统。

多个可执行格式——支持许多不同的可执行文件格式(例如a.out、ELF、java)。

均一性——为所有的逻辑文件系统,以及所有的硬件设备提供一个通用接口。

性能——提供对文件的高速访问。

安全——不会丢失或毁坏数据。

保密性——限制用户访问文件的许可权限和分配给用户的总的文件大小。目前,Linux系统支持大约15个文件系统:EXT、EXT2、XIA、MINIX、UMSDOS、MSDOS、VFAT、PROC、SMB、NCP、ISO9660、SYSV、HPFS、AFFS和UFS。毫无疑问,Linux系统支持的文件系统还会增加。一个文件系统中不仅包括含有数据的文件,而且还存储着文件系统的结构。文件系统中的信息必须是安全和保密的。第三十五页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统36Linux系统中的第一个文件系统是Minux,但它的文件名只能有14个字符,最大的文件长度是64MB。也正因此,1992年4月引进了第一个专门为Linux设计的文件系统——ext(extendedfilesystem),但ext的功能还是有限。最后在1993年又推出了一个新的文件系统——EXT2。当Linux引进ext文件系统时有了一个重大的改进:真正的文件系统从操作系统和系统服务中分离出来,在它们之间使用了一个接口层——虚拟文件系统VFS(VirtualFilesystem)。VFS允许Linux支持多种不同的文件系统,每个文件系统都要提供给VFS一个相同的接口。这样,所有的文件系统对系统内核和系统中的程序来说看起来都是相同的。Linux系统中的VFS层使得用户可以同时在系统中透明地挂接很多不同的文件系统。在Linux系统中,每一个单独的文件系统都是代表整个系统的树状结构的一部分。当挂接一个新的文件系统时,Linux把它添加到这个树状的文件系统中。所有系统中的文件系统,不管是什么类型,都挂接到一个目录下,并隐藏目录中原有的内容。这个目录叫做挂接目录或者挂接点。当文件系统卸载时,目录中的原有内容将再一次地显示出来。磁盘在初始化时被划分成几个逻辑分区,每一个逻辑分区可以使用一种文件系统,例如,EXT2文件系统。文件系统把存储在物理驱动器中的文件组织成一个树状的目录结构,可以存储文件的设备称为块设备。Linux文件系统把这些块设备当做简单的线形块的集合,而不管物理磁盘的结构如何。而将读写某一个设备块的请求转换成特定的磁道、扇区和柱面是通过设备的驱动程序实现的。因此,不同的设备控制器控制的不同设备中的不同文件系统在Linux中都可以同样地使用。文件系统甚至可以不在当地的系统中,也就是说,文件系统可以通过网络远程连接到本地磁盘上。第三十六页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统37当文件系统被作为子目录挂装时,在该设备上的所有目录和文件都将被视为挂装点的子目录。虚拟文件系统的用户不需要考虑哪种逻辑文件系统实现了目录树的哪个部分,也无需考虑哪个物理设备包含这些逻辑文件系统。这种抽象性在选择物理设备和逻辑文件系统时,提供了很大的方便,而这种方便性是Linux操作系统成功的重要因素之一。VFS能高速度及高效率地存取系统中的文件,与此同时它还得确保文件和数据的正确性。这两个目标有时可能相互矛盾。由于VFS在每个文件系统挂接和使用时,把文件系统的有关信息暂时保存在内存中,所以当内存中的信息改变时,例如,创建、写入和删除目录和文件时,系统要保证正确地升级文件系统中相关的内容。如果了解在系统内核中运行的文件系统的数据结构,那么也就能比较容易地理解文件系统读取的数据块的情况。系统缓存中最重要的就是缓冲区缓存,它被集成到每个单独的文件系统存取它们的块设备所使用的方法中。每当系统存取数据块时,数据块被放入到缓冲区缓存中,并且依照它们的状态保存到各种各样的队列中。缓冲区缓存中不仅保存了数据缓冲区,而且还可以帮助管理与块设备驱动程序之间的异步接口。为了支持虚拟文件系统,Linux使用了索引节点的概念。Linux使用索引节点来表示块设备上的文件。索引节点中包含了一些操作,根据文件所驻留的逻辑系统和物理系统的不同,这些操作的实现方法也会有所变化。从这层意义上讲,索引节点是虚拟的。索引节点接口使所有的文件在其他Linux子系统看起来都是一样的。索引节点可以用做一个存储位置,存储磁盘上与某个打开的文件相关的所有信息。索引节点存储相关缓冲、以块为单位的文件总长度,以及文件偏移量和设备块之间的映射。第三十七页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统381.EXT2文件系统EXT2文件系统是Linux系统中最为成功的文件系统,各种Linux的系统发布都将EXT2文件系统作为操作系统的基础。EXT2文件系统中的数据是以数据块的方式存储在文件中的。这些数据块具有同样的大小,并且其大小可以在EXT2创建时设定,每一个文件的长度都要补足到块的整数倍。EXT2通过使用索引节点(inode)数据结构来描述系统中的每一个文件。索引节点描述了文件中的数据占用了哪一个数据块,以及文件的存取权限、文件的修改时间和文件类型等信息。EXT2文件系统中的每一个文件都只有一个索引节点,而每一个索引节点都有一个惟一的标志符。文件系统中的所有的索引节点都保存在索引节点表中。EXT2中的目录只是一些简单的特殊文件(它们也使用索引节点描述),这些文件中包含指向目录入口的索引节点的指针。对于一个文件系统来说,某一个块设备只是一系列可以读写的数据块。文件系统无需关心数据块在设备中的具体位置,因为这是设备驱动程序的工作。每当文件系统需要从块设备中读取数据时,它就要求设备驱动程序读取整数数目的数据块。EXT2文件系统将它所占用的设备的逻辑分区分成了数据块组。每一个数据块组都包含一些有关整个文件系统的信息,以及真正的文件和目录的数据块。在EXT2文件系统中索引节点是一切的基础,文件系统中的每一个文件和目录都使用一个惟一的索引节点。每一个数据块组中的索引节点都保存在索引节点表中。数据块组中还有一个索引节点位图,它用来记录系统中已分配和未分配的索引节点。第三十八页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统39下面是EXT2的索引节点的一些主要的字段。

mode这里保存两个信息:一个是此索引节点描述的是什么,另一个是用户拥有的权限。例如,对于EXT2,一个索引节点可以描述文件、目录、符号连接、块设备、字符设备,以及FIFO结构。

OwnerInformation这是文件或目录所有者的用户和组标志符。这使得文件系统可以正确地授权某种存取操作。

Size文件的字节大小。

Timestamps索引节点建立的时间和索引节点最后修改的时间。

Datablocks指向存储此索引节点描述文件的数据块的指针。前12个指针是指向存储数据的物理数据块的指针,而后3个指针则包括不同级别的间接指针。例如,两级指针指向一个指向其他指针块的指针块,这意味着小于或者等于12个数据块的文件的存取速度要高于多于12个数据块的文件。超级块(Superblock)存储着描述文件系统的大小和形状的基本信息。文件系统的管理员可以使用其中的信息来使用和维护文件系统。一般情况下,当文件系统挂接时,系统只读取数据块组0中的超级块,但每一个数据块组中都包含一个超级块的副本,以防系统崩溃时使用。第三十九页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统402.虚拟文件系统(VFS)如图2.5所示为Linux系统内核中的VFS和实际文件系统之间的关系。VFS必须管理同时挂接在系统上的不同的文件系统。VFS通过使用描述整个VFS的数据结构和描述实际挂接的文件系统的数据结构来管理这些不同的文件系统。这里易于混淆的是,VFS和EXT2文件系统一样使用超级块和索引节点来描述系统中的文件。与EXT2中的索引节点一样,VFS的索引节点用来描述系统中的文件和目录。当一个文件系统初始化时,它将在VFS中登记。这些过程在操作系统初始化时完成。实际的文件系统或者内建到操作系统内核中,或者作为可装入模块在需要时装入。当一个基于块设备的文件系统挂接时,当然也包括根文件系统,VFS首先要读取它的超级块。每一个文件系统的超级块读取程序都必须先清楚文件系统的结构,然后把有关的信息添加到VFS的超级块数据结构中。VFS中保存了系统中挂接的文件系统的链表,以及这些文件系统对应的VFS超级块。每一个VFS超级块都包含一些信息和指向一些执行特别功能的子程序的指针。例如,代表挂接的EXT2文件系统的VFS超级块包含了一个指向EXT2索引节点读取程序的指针。这个EXT2索引节点读取程序,与其他文件系统索引节点的读取程序一样,把信息添加到VFS索引节点中的字段中。每一个VFS超级块都包含一个指向文件系统中第一个VFS索引节点的指针。对于根文件系统来说,第一个VFS索引节点是代表根目录(/)的索引节点。这种对应关系对于EXT2文件系统来说十分有效,但对于其他的文件系统则效果一般。第四十页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统41当系统中的进程存取目录和文件时,需要调用系统中的子程序来遍历搜索系统中的VFS索引节点。例如,键入ls或者cat命令将导致VFS搜索整个文件系统中的VFS索引节点。因为系统中的每一个文件和目录都由一个索引节点来表示,那么有些索引节点将经常会被重复地搜索。这些索引节点将保存在索引节点缓存中,这样将加快以后的存取速度。如果要找的索引节点不在索引节点缓存中,那么进程将调用一个特殊的系统程序来读取相应的索引节点。读取索引节点后,此索引节点将放在索引节点缓存中。最少用到的索引节点将被交换出索引节点缓存。第四十一页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统42设备管理操作系统的一个功能就是将用户和系统的硬件特性隔离。例如,虚拟文件系统(VFS)使得系统上挂接的文件系统具有相同的接口,使用户不必关心底层的硬件设备。计算机系统中的物理设备都有自己的硬件控制器。例如,键盘、鼠标和串行口是由SuperIO芯片控制的;IDE硬盘是由IDE控制器控制的,等等。每一个硬件控制器都有自己的控制及状态寄存器(CSR),而且随设备的不同而不同。CSR用来启动和停止设备、初始化设备和诊断设备错误。设备驱动程序一般集成在操作系统内核,这样,不同的应用程序就可以共享这些代码。设备驱动程序实际是处理或操作硬件控制器的软件,从本质上讲,它们是内核中具有高特权级的、驻留内存的、可共享的底层硬件处理例程。设备驱动程序的一个基本特点就是对设备的抽象处理。系统中的所有硬件设备看起来都与一般的文件一样,它们可以使用处理文件的标准系统调用来打开、关闭和读写。系统中的每一个设备都由一个设备文件来代表,例如,主IDE硬盘的设备文件是/dev/hda。对于块设备和字符设备来说,这些设备文件可以使用mknod命令创建。新建的设备文件使用主设备号和从设备号来描述此设备。网络设备的设备文件是当系统查找到网络设备并初始化网络控制器之后才建立的。一个设备驱动程序控制的所有设备有一个相同的主设备号,通过不同的从设备号来区分设备和它们的控制器。例如,主IDE硬盘的每一个分区都有一个不同的从设备号,这样,主IDE硬盘的第二个分区的设备文件是/dev/hda2。Linux系统使用主设备号和系统中的一些表来将系统调用中使用的设备文件映射到设备驱动程序中。第四十二页,共六十一页,2022年,8月28日第2章嵌入式LINUX操作系统43Linux系统支持三种类型的硬件设备:字符设备、块设备和网络设备。其中与文件子系统相关的两种类型是字符设备和块设备。字符设备是直接读取的,不必使用缓冲区,但是必须以串行的顺序依次访问。例如,系统的串行口/dev/cua0和/dev/cua1。块设备每次只能读取一定大小的块的倍数,通常一块是512字节或者1024字节。块设备通过缓冲区读写,并且可以随机地读写。块设备可以通过它们的设备文件存取,但通常是通过文件系统存取。只有块设备支持挂接的文件系统。网络设备是通过BSD套接字界面存取的。Linux系统支持多种设备,这些设备的驱动程序之间有以下这些共同的特点。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论