《嵌入式操作系统优秀课件.ppt》由会员分享,可在线阅读,更多相关《嵌入式操作系统优秀课件.ppt(61页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、嵌入式操作系统第1页,本讲稿共61页 第2章 嵌入式LINUX操作系统 22.1 Linux及其应用Linux操作系统是UNIX操作系统的一种克隆系统。它诞生于1991年的10月5日(这是第一次正式向外公布的时间)。此后借助于因特网,经过全世界各地计算机爱好者的共同努力,现已成为当今世界上使用最多的一种UNIX类操作系统,并且使用人数还在迅猛增长。2.1.1 Linux与UNIX和GNU2.1.2 Linux的特点2.1.3 Linux的发展及应用第2页,本讲稿共61页 第2章 嵌入式LINUX操作系统 3Linux与UNIX和GNU UNIX操作系统是美国贝尔实验室的Ken.Thompson
2、和Dennis Ritchie于1969年夏在DEC PDP-7小型计算机上开发的一个分时操作系统。Ken Thompson在1969年夏天利用一个月的时间开发了UNIX操作系统的原型。后经Dennis Ritchie于1972年用移植性很强的C语言进行了改写,使得UNIX系统在大专院校得到了推广。MINIX系统是由Andrew S.Tanenbaum(AST)于1987年开发的,主要用于学生学习操作系统原理。AST工作在荷兰Amsterdam的Vrije大学,并从事数学与计算机科学系统研究,是ACM和IEEE的资深会员(全世界也只有很少人是两会的资深会员)。GNU计划和自由软件基金会FSF(
3、the Free Software Foundation)是由Richard M.Stallman于1984年一手创办的,旨在开发一个类似UNIX,并且是自由软件的完整操作系统:GNU系统(GNU是“GNUs Not UNIX”的递归缩写,它的发音为“gun-NEW”)。各种使用Linux作为核心的GNU操作系统正在被广泛地使用。虽然这些系统通常被称为“Linux”,但是Stallman认为,以严格意义上讲,它们应该被称为GNU/Linux系统。到20世纪90年代初,GNU项目已经开发出许多高质量的免费软件,其中包括有名的emacs编辑系统、bash shell程序、gcc系列编译程序、gdb
4、调试程序,等等。这些软件为Linux操作系统的开发创造了一个合适的环境,这也是Linux能够诞生的基础之一,以至于目前许多人都将Linux操作系统称为“GNU/Linux”操作系统。第3页,本讲稿共61页 第2章 嵌入式LINUX操作系统 4POSIX(Portable Operating System Interface for Computing Systems)是由IEEE和ISO/IEC开发的一组标准。该标准是基于现有UNIX的实践经验,描述了操作系统的调用服务接口。用于保证编制的应用程序可以在源代码一级上、在多种操作系统上移植和运行。它是在1980年一个UNIX用户组(usr/gro
5、up)的早期工作基础上完成的。20世纪90年代初,POSIX标准的制定处于最后投票敲定的时候,此时也正是Linux刚刚起步的时候,这个UNIX标准为Linux提供了极为重要的信息,使得Linux能够在标准的指导下进行开发,并能够与绝大多数UNIX操作系统兼容。通过上述说明,我们可以对上述Linux的5大支柱归纳如下:UNIX操作系统Linux就是UNIX的一种克隆系统。UNIX的重要性就不用多说了。MINIX操作系统MINIX操作系统也是UNIX的一种克隆系统,它于1987年由著名计算机教授Andrew S.Tanenbaum开发完成。由于MINIX系统的出现并且提供源代码(只能免费用于大学内
6、),在全世界的大学中刮起了学习UNIX系统旋风。Linux刚开始就是参照MINIX系统于1991年才开始开发。GNU计划开发Linux操作系统,以及Linux上所用大多数软件基本上都出自GNU计划。Linux只是操作系统的一个内核,没有GNU软件环境(如bash shell),则Linux将寸步难行。POSIX标准该标准在推动Linux操作系统以后朝着正规路上发展起着重要的作用,是Linux前进的灯塔。Internet如果没有Internet网,没有遍布全世界的无数计算机黑客的无私奉献,那么Linux最多只能发展到0.13(0.95)版的水平第4页,本讲稿共61页 第2章 嵌入式LINUX操作
7、系统 5Linux的特点 1开放性是指系统遵循世界标准规范,特别是遵循开放系统互联(OSI)国际标准。凡遵循国际标准所开发的硬件和软件,都能彼此兼容,可方便地实现互联。Linux采用GPL授权,除了把源代码公开以外,任何人都可以自由使用、修改、散布;而Linux核心本身采用模块化设计,让人很容易增减功能,由于Linux具有这样高的可伸缩性,所以可以调出最适合我们硬件平台的核心出来。2多用户是指系统资源可以被不同用户各自拥有并使用,即每个用户对自己的资源有特定的权限,互不影响。Linux和UNIX都具有多用户的特性。3多任务是现代计算机最主要的一个特点。它是指计算机同时执行多个程序,而且各个程序
8、的运行互相独立。Linux系统调度每一个进程平等地访问微处理器。由于CPU的处理速度非常快,其结果是,启动的应用程序看起来好像在并行运行。4稳定性强,Linux不属于任何一家公司,但它却拥有全世界愿意投入自由软件的开发人员。在全球各处都有无数的人参与Linux核心的改进、调试与测试,也正因此造就了稳定度高的Linux。所以,Linux虽不是商业的产物,但它的质量却不逊于商业产品。5设备独立性,是指操作系统把所有外部设备统一当做文件来看待,只要安装它们的驱动程序,任何用户都可以像使用文件一样,操纵、使用这些设备,而不必知道它们的具体存在形式。另外,由于用户可以免费得到Linux的内核源代码,因此
9、,用户可以修改内核源代码,以便适应新增加的外部设备。第5页,本讲稿共61页 第2章 嵌入式LINUX操作系统 66提供了丰富的网络功能完善的内置网络是Linux的一大特点。Linux在通信和网络功能方面优于其他操作系统。Linux为用户提供了完善的、强大的网络功能,包括支持Internet、文件传输和远程访问。7可靠的系统安全在Linux操作系统中采取了许多安全技术措施,包括对读、写进行权限控制、带保护的子系统、审计跟踪、核心授权等,这些措施为网络多用户环境中的用户提供了必要的安全保障。8良好的可移植性可移植性是指将操作系统从一个平台转移到另一个平台,并使它仍然能按其自身的方式运行的能力。Li
10、nux一开始是基于Intel 386机器设计的,但是随着网络的散布,加上有许多工程师致力于各式平台的移植,使得Linux可以在x86、MIPS、ARM/StrongARM、PowerPC、Motorola 68k、Hitachi SH3/SH4、Transmeta等平台上运行。这些平台几乎覆盖了所有嵌入式系统的CPU种类,这样,在硬件平台设计时,使得可以考虑的CPU种类增加了不少。9应用软件多自由软件世界里有个很大的特点就是软件多,授权几乎都是采用GPL方式,大家都可以自由参考与使用,但是因为这些软件多半是由设计者利用空余时间开发的,不以赢利为目的,所以并不能担保这些软件完全没有问题。尽管如此
11、,仍有许多优秀软件出现,例如,大家熟知的KDE与GNOME便是很好的证明。第6页,本讲稿共61页 第2章 嵌入式LINUX操作系统 7Linux的发展及应用 1991年10月5日,Linus Torvalds在新闻组comp.os.minix发布了大约有1万行代码的Linux v0.01版本。1992年,大约有1000人在使用Linux,基本上都属于真正意义上的黑客。1993年,大约有100余名程序员参与Linux内核代码编写/修改工作,其中核心组由5人组成,此时Linux 0.99的代码大约有十万行,用户大约有10万个左右。1994年3月,Linux 1.0发布,代码量为17万行,正式采用G
12、PL协议。Linux的代码中充实了对不同硬件系统的支持,大大提高了跨平台移植性。1995年,Linux可在Intel、Digital,以及Sun SPARC处理器上运行了,用户量也超过了50万,相关介绍Linux的Linux Journal杂志的发行也超过10万册。1996年6月,Linux 2.0内核发布,此内核大约有40万行代码,并可以支持多个处理器。此时的Linux已经进入了实用阶段,全球大约有350万人使用。1997年夏,好莱坞影片泰坦尼克号在制作特效中使用的160台Alpha图形工作站中,有105台采用了Linux操作系统。1998年是Linux迅猛发展的一年。RedHat 5.0获
13、得了InfoWorld的操作系统奖项。4月,Mozilla代码发布,成为Linux图形界面上的王牌浏览器。王牌搜索引擎“Google”现身,采用的也是Linux服务器。Mysql数据库充分得到发展。12月,IBM发布了适用于Linux的文件系统AFS 3.5,以及Jikes Java编辑器和Secure Mailer及DB2测试版,IBM的此番行为,可以看做是与Linux的第一次亲密接触。迫于Windows和Linux的压力,Sun逐渐开放了Java协议,并且在UltraSparc上支持Linux操作系统。由此可见,1998年可以说是Linux与商业接触的一年。第7页,本讲稿共61页 第2章
14、嵌入式LINUX操作系统 81999年,IBM宣布与Redhat公司建立伙伴关系,以确保Redhat在IBM机器上正确运行。3月,第一届LinuxWorld大会的召开,象征Linux时代的来临。IBM、Compaq和Novell宣布投资Redhat公司,以前一直对Linux持否定态度的Oracle公司也宣布投资。5月,SGI公司宣布向Linux移植其先进的XFS文件系统。7月,IBM启动对Linux的支持服务,并发布了Linux DB2。2000年初始,Sun公司在Linux的压力下宣布Solaris8降低售价。事实上,Linux对Sun造成的冲击远比对Windows来得更大。2月,Red H
15、at发布了嵌入式Linux的开发环境,Linux在嵌入式行业的潜力逐渐被发掘出来。2001年Oracle宣布在OTN上的所有会员都可免费索取Oracle 9i的Linux版本。IBM则决定投入10亿美元扩大Linux系统的应用。到了5月,微软公开反对“GPL”,此举引起了一场大规模的论战。8月,红色代码爆发,引得许多站点纷纷从Windows操作系统转向Linux操作系统。12月,Red Hat为IBM s/390大型计算机提供了Linux解决方案。2002年是Linux企业化的一年。2月,微软公司迫于各州政府的压力,宣布扩大公开代码行动,这是Linux开源带来的深刻影响的结果。3月,内核开发者
16、宣布新的Linux系统支持64位的计算机。2003年1月,NEC宣布将在其手机中使用Linux操作系统,代表着Linux成功进军手机领域。2004年6月的统计报告显示在世界500强超级计算机系统中,使用Linux操作系统的已经占到了280席,抢占了原本属于各种UNIX的份额。9月HP开始网罗Linux内核代码人员,以影响新版本的内核朝对HP有利的方式发展,而IBM则准备推出OpenPower服务器,仅运行Linux系统。第8页,本讲稿共61页 第2章 嵌入式LINUX操作系统 9Linux的应用和优势(以银行为例)银行业是中国各行业中开展信息化建设最早的行业之一,其信息化建设投入力度大,信息化
17、水平高,在各行业的IT应用和系统建设中走在前列。(1)银行业的数据量大且集中决定了其对主机、存储设备、网络设备等硬件设备需求很大;同时对存储管理、数据仓库、网络管理、网络安全、CRM等方面的软件需求也不小。正由于银行业的数据量大且集中,因此金融安全问题也越发突出。Linux的高可靠性和安全性是它在这一行业中应用的有力保障。(2)对银行业而言,成本因素在整体经济环境欠佳的今天显得尤其重要。选择Linux的动力很大程度上来自于各个企业公司预算的减少。(3)Linux系统所具有的优良集群特性也是吸引更多客户的原因。Linux集群系统能够让客户相对落后的P或P计算机变成可以处理复杂任务的超级计算机系统
18、。这对客户来说是非常有吸引力的。(4)北京市商业银行综合业务系统建设采用了基于IBM Server i系列服务器的Linux解决方案。该解决方案从整体上减少了总拥有成本,并且减少了系统管理的复杂性,实现了对人员、财政及信息技术的有效管理,同时还提高了服务器管理能力。(5)再以印度工业开发银行(IDBI)为例。他们自1995年开始使用Linux系统从事关键的电话银行、资产追踪及人力资源管理等业务,IDBI因此节省的IT预算达到70%。(6)如今有越来越多的商业公司采用Linux作为操作系统,例如,科学工作者使用Linux来进行分布式计算,ISP使用Linux配置Intranet服务器、电话拨号服
19、务器等网络服务器,CERN(西欧核子中心)采用Linux做物理数据处理。第9页,本讲稿共61页 第2章 嵌入式LINUX操作系统 102.2 Linux内核由于的源代码是完全公开的,任何人只要遵循GPL,就可以对内核加以修改并发布给他人使用。因此,在广大编程人员的支持下,Linux的内核版本不断更新,新的内核修改了旧内核的缺陷,并增加了许多新的特性。用户如果想在自己的系统中使用这些新的特性,或想根据自己的系统量身定制更高效、更稳定可靠的内核,只需要重新编译内核。当内核的编译工作完成之后,会生成一个可执行的二进制文件,该二进制文件放入嵌入式系统的ROM中,可以完成系统的上电、复位自动运行。2.2
20、.1 Linux的内核特征2.2.2 进程管理2.2.3 内存管理2.2.4 文件系统管理2.2.5 设备管理2.2.6 进程间通信机制第10页,本讲稿共61页 第2章 嵌入式LINUX操作系统 11Linux的内核特征 内核是操作系统的内部核心程序,它向外部提供了对计算机设备的核心管理调用。操作系统的代码分为以下两部分,内核所在的地址空间称为内核空间,外部管理程序与用户进程所占据的地址空间称为外部空间(用户空间)。通常,一个程序会跨越两个空间。当执行到内核空间的一段代码时,称程序处于核心态;而当程序执行到外部空间代码时,称程序处于用户态。单一内核(Monolithic Kernel)曾经是操
21、作系统的主流,它是指操作系统中所有的系统相关功能都被封装在内核中。它们与外部程序处在不同的内存地址空间中,并通过各种方式防止外部程序直接访问内核中的数据结构。程序只有通过一套称作系统调用(System Call)的界面访问内核结构。近些年来,微内核(Micro Kernel)结构逐渐流行起来,成为操作系统的主要潮流。在微内核结构中,操作系统的内核只需要提供最基本、最核心的一部分操作(例如,创建和删除任务、内存管理、中断管理等)即可,而其他管理程序(如文件系统、网络协议栈等)则尽可能放在内核以外。这些外部程序可以独立运行,并对外部用户程序提供操作系统服务,服务之间使用进程间通信机制(IPC)进行
22、交互。如同面向对象程序设计带来的好处一样,微内核使操作系统内部结构变得简单清晰。在内核以外的外部程序分别独立运行,其间并不互相关联。这样,可以对这些程序分别进行维护和拆装,只要遵循已经规定好的界面,就不会对其他程序有任何干扰。这使得程序代码在维护上十分方便,体现了面向对象式软件的结构特征。第11页,本讲稿共61页 第2章 嵌入式LINUX操作系统 12微内核的结构也存在着不足之处。首先,程序代码之间的相互隔离,使得整个系统丧失了许多优化的机会。其次,部分资源浪费在外部进程之间的通信上,这样,微内核结构在效率上必然低于传统的单一内核结构,这些效率损失将作为结构精简的代价。总体上说,在当前的硬件条
23、件下,微内核在效率上的损失小于其在结构上获得的收益,故而选取微内核成为操作系统的一大潮流。然而,Linux系统恰恰使用了单一内核结构。这是由于Linux是一个实用主义的操作系统。Linus Torvalds将代码执行效率作为自己操作系统的第一要务。在这样的发展过程中,参与Linux系统开发的程序员大多数为世界各地的黑客们。比起结构的清晰,他们更加注重功能的强大和高效率的代码。于是,他们将大量的精力花在优化代码上,而这样的全局性优化必然以损失结构精练作为代价,导致Linux中的每个部件都不能被轻易拆出,否则,必然破坏整体效率。虽然Linux是一个单一内核操作系统,但它与传统的单一内核UNIX操作
24、系统不同。在普通的单一内核系统中,所有内核代码都是被静态编译连入的。而在Linux中,可以动态装入和卸载内核中的部分代码。Linux中将这样的代码段称为模块(Module),并对模块给予了强有力的支持。在Linux中,可以在需要时自动装入和卸载模块。Linux的内核为非抢占式的(Non-preemptive)。这就是说,Linux并不能通过改变优先权来影响内核当前的执行流程。Linux并不是一个“硬”实时操作系统。Linux操作系统的内核稳定而高效,以独占的方式执行最底层任务,来保证其他程序的正常运行。它是整个操作系统的核心,具有独特的性质。第12页,本讲稿共61页 第2章 嵌入式LINUX操
25、作系统 13进程管理进程是运行于自己的虚拟地址空间的一个程序。可以说,任何在Linux系统下运行的都是进程。Linux系统中包括下面几种类型的进程。交互进程:该进程是由shell控制和运行的。它既可以在前台运行,也可以在后台运行。批处理进程:该进程不属于某个终端,被提交到一个队列中以便顺序执行。守护进程:该进程只有在需要时才被唤起在后台运行。它一般在Linux启动时开始执行。进程是动态的,在处理器执行机器代码时进程一直在变化。进程不但包括程序的指令和数据,而且包括程序计数器和CPU的所有寄存器,以及存储临时数据的进程堆栈。由此可见,正在执行的进程包括处理器当前的一切活动。Linux是一个多进程
26、的操作系统,每个进程都有自己的权限和任务,某一进程的失败一般不会导致其他进程的失败,进程之间可以通过由内核控制的机制相互通讯。在进程的整个运行期间,它将会用到各种系统资源,会用到CPU运行它的指令,需要物理内存保存它的数据。它可能打开和使用各种文件,直接或间接地使用系统中的各种物理设备。Linux系统内核必须了解进程本身的情况和进程所用到的各种资源,以便在多个进程之间合理地分配系统资源。系统中最为宝贵的资源是CPU,因为在一般情况下,一个系统只有一个CPU。Linux是一个多进程的操作系统,所以,其他的进程必须等到正在运行的进程空闲CPU后才能运行。当正在运行的进程等待其他的系统资源时,Lin
27、ux内核将取得CPU的控制权,并将CPU分配给其他正在等待的进程。内核中的调度算法决定将CPU分配给哪一个进程。第13页,本讲稿共61页 第2章 嵌入式LINUX操作系统 14进程管理程序能够进行进程的创建、激活、运行、阻塞、再运行、释放,以及删除。进程管理程序执行下列操作:在多进程(或者任务、线程)系统中执行每一个进程,使得进程状态可以切换。进程的顺序经过以下这些状态:“创建”、“就绪或者激活”、“产生”(创建且激活)、“运行”、“阻塞”、“再运行”、“完成”,以及“完成”之后的“就绪”(当进程中存在无限循环时)。最后,释放或者删除(在长进程中,阻塞和再运行可以发生很多次)。进程管理程序实现
28、以下功能:使进程能够顺序执行或者在需要资源时发生阻塞,并使其在资源可用时继续运行。为进行资源管理(包括CPU上的进程调度)实现了与资源管理程序的逻辑链接。限制某些资源只在某些进程间共享。按照系统的资源分配机制分配资源。管理系统中的进程和资源。第14页,本讲稿共61页 第2章 嵌入式LINUX操作系统 151进程与线程现在的嵌入式操作系统几乎都被要求能够与个人计算机上的操作系统一样,提供多任务(Multitasking)功能。但是多数的嵌入式系统只有一个处理器,要完成这样的要求,操作系统必须为这些不同的任务分配执行时间,而这些任务就要轮流利用分配到的执行时间来完成工作。为了方便管理这些任务,嵌入
29、式操作系统会分别以一个执行单位来看待一项工作或一个程序,这个执行单位在不同的嵌入式操作系统中会有不同的名称与意义,但是基本的思想都是为了让不同的程序共同分享、使用有限的硬件资源,然后让用户在使用系统时,好像可以“同时”执行多个应用程序。Linux采用所谓“继承”的方法来进行资源分配。每个新的进程都必须先从父进程(Parent Process)中去继承一份系统资源,基本上就是子进程(Child Process)分配到另外一块独立的内存空间,然后从父进程的内存空间中把所有的数据完完全全拷贝过来,再通过参数的设置决定是否与父进程分享资源,并决定子进程属于重优先权值进程(Heavy Weight Pr
30、ocess)还是轻优先权值进程(Light Weight Process)。轻优先权值进程在Linux里也称为线程。第15页,本讲稿共61页 第2章 嵌入式LINUX操作系统 162进程的状态不论采用何种方式,嵌入式操作系统必须管理多任务的执行与切换,因为某一时刻真正被CPU执行的任务只有一个,所以当同时存在许多不同的任务时,每个任务的状态都不相同。一个进程在其生存期内,可处于一组不同的状态下,称为进程状态。如图2.2所示。操作系统会以一个特殊的数据结构来代表一个进程。这个特殊的数据结构会记录一些重要的数据,通常被称为PCB(Process Control Block)或TCB(Task Co
31、ntrol Block)。它除了包含task context(任务上下文)之外,还会记录句柄、优先级,以及一些进程的附属数据,这些数据提供了调度程序(Scheduler)调度时所需的全部信息。进程状态就保存在TCB的state字段中。内核程序通过任务向量表对进程进行管理,每个进程在向量表中占有一项。在Linux系统中,任务向量表项是一个task_struct任务结构指针(在Linux中task和process互用)。任务数据结构定义在头文件include/linux/sched.h中。这个数据结构也就是前面提到的TCB或PCB。当新的进程创建的时候,进程管理模块从系统内存中分配一个新的task
32、_struct,并增加到task向量表中。为了更容易查找,用current指针指向当前运行的进程。当一个进程在执行时,CPU的所有寄存器中的值、进程的状态,以及堆栈中的内容被称为该进程的上下文。当内核需要切换(switch)至另一个进程时,它就需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够恢复到切换时的状态并执行下去。在Linux中,当前进程的上下文均保存在进程的任务数据结构中。第16页,本讲稿共61页 第2章 嵌入式LINUX操作系统 17第17页,本讲稿共61页 第2章 嵌入式LINUX操作系统 18 运行状态(TASK_RUNNING),当进程正在被CP
33、U执行,或已经准备就绪随时可由调度程序执行时,称该进程处于运行状态(running)。进程可以在内核态运行,也可以在用户态运行。当系统资源已经可用时,进程就被唤醒而进入准备运行状态,该状态称为就绪态。这些状态在内核中表示方法相同,都被称为处于TASK_RUNNING状态。可中断睡眠状态(TASK_INTERRUPTIBLE),当进程处于可中断等待状态时,系统不会调度该进程执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(运行状态)。不可中断睡眠状态(TASK_UNINTERRUPTIBLE),不可中断睡眠状态与可中断睡眠状态类似。但处于该
34、状态的进程只有被使用wake_up()函数明确唤醒时,才能转换到可运行的就绪状态。暂停状态(TASK_STOPPED),当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态,正在调试的进程可以处在停止状态。僵死状态(TASK_ZOMBIE),当进程已停止运行,但其父进程还没有询问其状态时,则称该进程处于僵死状态。只有当进程从“内核运行态”转移到“睡眠状态”时,内核才会进行进程切换操作。在内核态下运行的进程不能被其他进程抢占,而且一个进程不能改变另一个进程的状态。为了避免进程切换时造成内核数据错误,内核
35、在执行临界区代码时会禁止一切中断。第18页,本讲稿共61页 第2章 嵌入式LINUX操作系统 193进程的创建进程的创建是指为创建的进程定义地址空间(存储器块),并为进程定义资源。Linux系统采用继承的方式创建进程。进程管理程序在创建进程时分配TCB,并对它进行管理。TCB是进程管理程序使用的进程描述符。其他OS单元可以在必要的时候查询进程的TCB。系统启动的时候运行在核心态,这时,只有一个进程:初始化进程。初始化进程是一个在处理器重启时执行存储器指令,然后调用OS的进程。处理器随后开始执行创建的所有进程。像所有其他进程一样,初始进程有一组用堆栈、寄存器等表示的机器状态。当系统中的其他进程创
36、建和运行时,这些信息存在初始进程的task_struct数据结构中。在系统初始化结束的时候,初始进程启动一个核心线程(init)然后执行空闲循环,即什么也不做。也就是说,当处理器没有什么可以做的时候,调度程序会运行这个空闲的进程。这个空闲进程的task_struct是惟一一个不是动态分配而是在核心连接的时候静态定义的,为了不至于混淆,叫做init_task。init核心进程拥有进程标志符1,是系统的第一个真正的进程。它执行系统的一些初始化的设置(比如,打开系统控制器,安装根文件系统等),然后执行系统初始化程序。根据系统的不同,初始化程序可能是/etc/init,/bin/init或/sbin/
37、init其中之一。init程序使用/etc/inittab作为脚本文件创建系统中的新进程,这些新进程自身可能创建新的进程。例如,getty进程可能会在用户试图登录的时候创建一个login的进程。系统中的所有进程都是init核心线程的后代。第19页,本讲稿共61页 第2章 嵌入式LINUX操作系统 20新进程的创建是通过克隆旧的进程,或者说克隆当前的进程来实现的。一个新的任务是通过系统调用创建的(fork或clone),克隆发生在核心的核心态。在系统调用的最后,产生一个新的进程,等待调度程序选择它运行(在新进程的创建未完成之前,为了防止这个还未处理完成的新建进程被调度函数执行,应该将新进程状态置
38、为不可中断的等待状态)。在系统的物理内存中为这个克隆进程的堆栈(用户和核心)分配一个或多个物理的页用于新的task_struct数据结构。一个进程标志符将会创建,它在系统的进程标志符组中是惟一的。新的task_struct进入task向量表中,旧的(当前的)进程的task_struct的内容拷贝到克隆的task_struct。克隆进程的时候,Linux允许两个进程共享资源而不是拥有不同的拷贝,包括进程的文件,信号处理和虚拟内存。共享这些资源的时候,它们相应的count字段相应增减,这样,Linux在两个进程都停止使用之前不会释放这些资源。例如,如果克隆的进程要共享虚拟内存,它的task_str
39、uct会包括一个指向原来进程的mm_struct指针,mm_struct的count域增加,表示当前共享它的进程。4进程的调度Linux进程是抢占式的。被抢占的进程仍然处于TASK_RUNNING状态,只是暂时没有被CPU运行。进程的抢占发生在进程处于用户态执行阶段,在内核态执行时是不能被抢占的。为了能让进程有效地使用系统资源,又能使进程有较快的响应时间,Linux中采用基于优先级排队的调度策略。通常,核心会以分时(Time Slicing)的观念让多任务共享CPU资源,即将CPU执行的时间分成一段段的,每个程序会利用分配到的时间来执行任务。每一段的执行时间到了,就必须轮换下一个任务执行。至于
40、轮到哪一个任务来执行,必须由核心的调度程序来决定。第20页,本讲稿共61页 第2章 嵌入式LINUX操作系统 21在所有的进程中,部分运行于用户态,部分运行于核心态。底层的硬件支持这些状态的方式各不相同,但是通常有一个安全机制从用户态转入核心态并转回来。用户态比核心态的权限低很多。每一次进程执行一个系统调用,它都从用户态切换到核心态并继续执行。这时,让核心执行这个进程。在Linux中,进程不是通过互相争夺成为当前运行的进程,因为它们无法停止正在运行的其他进程而执行自身。每一个进程在它必须等待一些系统事件的时候会放弃CPU。例如,一个进程可能不得不等待从一个文件中读取一个字符,这个等待发生在核心
41、态的系统调用中,进程使用了库函数打开并读文件,库函数又执行系统调用从打开的文件中读入字节。这时,等候的进程会被挂起,另一个合适的进程将会被选择执行。由于进程经常调用系统调用,所以经常需要等待。由于即使进程执行到需要等待,也有可能会用去不均衡的CPU时间,所以Linux使用抢先式的调度。用这种方案,每一个进程允许运行少量一段时间,通常为200毫秒,当这段时间过去,选择另一个进程运行,原来的进程等待一段时间直到它又重新运行。这个时间段就叫做时间片。调度程序的任务就是选择当前可运行的进程中最值得运行的一个进程。一个可以运行的进程是一个只等待CPU的进程。Linux使用合理而简单的基于优先级的调度算法
42、在系统当前的进程中进行选择。当它选择了准备运行的新进程,就保存当前进程的状态、与处理器相关的寄存器,以及其他需要保存的上下文信息到进程的task_struct数据结构中。然后恢复要运行的新的进程的状态(又和处理器相关),把系统的控制交给这个进程。第21页,本讲稿共61页 第2章 嵌入式LINUX操作系统 22为了公平地在系统中所有可以运行(runnable)的进程之间分配CPU时间,调度程序在每一个进程的task_struct结构中保存了以下信息(参见Linux核心源文件kernel/sched.c中的函数schedule())。Policy 进程的调度策略。Linux有两种类型的进程:普通和
43、实时。实时进程比所有其他进程的优先级高。如果有一个实时的进程准备运行,那么它总是先被运行。实时进程有两种策略:循环或先进先出(round robin and first in first out)。在循环的调度策略下,每一个实时进程依次运行,而在先进先出的策略下,每一个可以运行的进程按照它在调度队列中的顺序运行,这个顺序不会改变。Priority 进程的调度优先级。也是指它允许运行时可以使用的时间量(jiffies)。可以通过系统调用或者renice命令来改变一个进程的优先级。Rt_priority Linux支持实时进程。这些进程比系统中其他非实时的进程拥有更高的优先级。这个域允许调度程序赋
44、予每一个实时进程一个相对的优先级。实时进程的优先级可以用系统调用来修改。Counter 这是进程可以运行的时间量(jiffies)。进程启动的时候等于优先级(priority)的数值,每一个时钟周期递减1。调度程序从核心的多个地方运行。它可以在把当前进程放到等待队列之后运行,也可以在系统调用之后进程从核心态返回用户态之前运行。需要运行调度程序的另一个原因是系统时钟刚好把当前进程的计数器(counter)置成0。第22页,本讲稿共61页 第2章 嵌入式LINUX操作系统 23每一次运行调度程序会完成以下工作:kernel work 运行bottom half handler并处理系统的调度任务队
45、列。Current poccess 在选择另一个进程之前处理当前进程。如果当前进程的调度策略是循环则将它放到运行队列的最后。如果任务是可中断的而且它上次调度的时候收到过一个信号,将它的状态变为RUNNING。如果当前进程超时,将它的状态成为RUNNING。如果当前进程的状态为RUNNING则保持此状态。将不是RUNNING或者INTERRUPTIBLE的进程从运行队列中删除。这意味着当调度程序查找最值得运行的进程时不会考虑这样的进程。Process Selection 查看运行队列中的进程,查找最值得运行的进程。Swap Processes 如果最值得运行的进程不是当前进程,当前进程必须被挂起
46、,运行新的进程。一个进程运行时会使用系统的CPU、寄存器和物理内存。每一次它调用例程都通过寄存器或者堆栈传递参数、保存数值等。可见,当调度程序运行的时候,它是在当前进程的上下文中运行。它可能处于特权模式:核心态,但是它仍旧运行在当前进程的上下文中。当这个进程需要挂起时,它的所有机器状态,包括程序计数器(PC)和所有的处理器寄存器,必须存到进程的task_struct数据结构中。然后,加载新进程的所有机器状态。这种操作依赖于系统,不同CPU的实现方法也不相同,不过,通常都是通过一些硬件的帮助来实现。第23页,本讲稿共61页 第2章 嵌入式LINUX操作系统 24具体调度过程如下:schedule
47、()函数首先扫描任务数组。通过比较每个就绪态(TASK_RUNNING)任务的运行时间递减计数counter的值来确定当前哪个进程运行的时间最少。哪一个任务的counter值大,就表示运行时间还不长,于是就选中该进程,并使用任务切换宏函数切换到该进程运行。如果此时所有处于TASK_RUNNING状态进程的时间片都已经用完,系统就会根据每个进程的优先权值priority,对系统中所有进程(包括正在睡眠的进程)重新计算每个任务需要运行的时间片值counter。计算的公式是:counter counter/2 priority然后schedule()函数重新扫描任务数组中所有处于TASK_RUNNI
48、NG的状态,重复上述过程,直到选择出一个进程为止。最后调用switch_to()执行实际的进程切换操作。执行实际进程切换的任务由switch_to()宏定义的一段汇编代码完成。在进行切换之前,switch_to()首先检查要切换到的进程是否就是当前进程,如果是,则什么也不做,直接退出。否则就把内核全局变量current置为新任务的指针,然后完成上下文的切换。第24页,本讲稿共61页 第2章 嵌入式LINUX操作系统 255进程的终止当一个进程结束了运行或在半途终止了运行,那么内核就需要释放该进程所占用的系统资源。这包括进程运行时打开的文件、申请的内存等。当一个用户程序调用exit()系统调用时
49、,则执行内核函数do_exit()。该函数会首先释放进程代码段和数据段占用的内存页面,关闭进程打开着的所有文件等。如果进程有子进程,则让init进程作为其所有子进程的父进程,然后把进程状态置为僵死状态TASK_ZOMBIE,并向其原父进程发送SIGCHLD信号,通知其某个子进程已经终止。最后do_exit()调用调度函数去执行其他进程。由此可见,在进程被终止时,它的任务数据结构仍然保留着,因为其父进程还需要使用其中的信息。子进程在执行期间,父进程通常使用wait()或waitpid()函数等待其某个子进程终止。当等待的子进程被终止并处于僵死状态时,父进程就会把子进程运行所使用的时间累加到自己进
50、程中。最终释放已终止子进程任务数据结构所占用的内存页面,并置空子进程在任务数组中占用的指针项。第25页,本讲稿共61页 第2章 嵌入式LINUX操作系统 26内存管理内存管理(Memory Management)系统是操作系统中最为重要的部分,内存管理程序子系统负责控制进程对硬件内存资源的访问。这是通过硬件内存管理单元(Memory Management Unit,MMU)来完成的,该单元提供进程内存引用与计算机的物理内存之间的映射。内存管理程序子系统为每个进程都维护一个这样的映射关系,使得两个进程就可以访问同一个虚拟内存地址,而实际使用的却是不同的物理内存位置。此外,内存管理程序子系统支持交