第四章 嵌入式系统软件基础知识

4.1 嵌入式软件基础

        嵌入式软件是指应用在嵌入式计算机系统当中的各种软件。在嵌入式系统的发展初期,软件的种类很少,基本上都是硬件的附属品。随着嵌入式系统应用的发展,嵌入式软件形成了一个完整、独立的体系。

4.1.1 嵌入式系统

        嵌入式计算机系统是与特定功能的设备集成在一起、且隐藏在这个功能系统内部为预定任务而设计的计算机系统。该计算机可对设备的状态进行采集,按照设备所要求的进行计算,计算结果输出到设备的某些部件,控制某些操作,同时将信息显示给操作者。

典型的嵌入式系统如图:

        上述嵌入式系统的输入、处理、输出的各个部分,一般情况下都是通过软件运行完成的。因此嵌入式软件是嵌入式系统的重要组成部分,而且体现系统的思想、方法和规律。

        嵌入式系统一般是实时系统,实时性就体现在从输入到形成输出所需的时间。实时系统又进一步定义为硬实时系统软实时系统两种。

实时系统分类及其特性如表:

嵌入式系统具有以下特征:

        (1)嵌入式系统的时间敏感性。嵌入式实时系统对事件响应都是有要求的;

        (2)嵌入式系统的可靠性和安全性。

        (3)嵌入式软件的复杂性。软件复杂度取决于问题规模和复杂度。

4.1.2 嵌入式软件

软件的复杂性、重要性体现在:

        (1)从计算机理论和技术发展趋势来说,硬件和软件没有明确界限,原来使用硬件实现的功能尽可能地向软件迁移,技术进步越来越显现在软件方面;

        (2)软件的特殊性导致了需要有特殊的规则保证系统的安全性和可靠性。

与其他行业比较,软件行业具有以下鲜明的特点:

        (1)抽象性:软件直接反映了人的思维逻辑实体,同时几乎没有具体物理实体,且没有明显的制造过程

        (2)客观问题越来越复杂,软件页随之越来越复杂,而且软件技术的进步速度落后于需求增长速度。

        (3)相对于通用硬件,软件开发成本昂贵

        (4)软件运行和使用没有磨损和老化现象

        (5)软件对硬件和环境有着不同程度的依赖性

        (6)大多数软件是新开发的,通过已有构件组装技术尚不成熟

        (7)软件工作结果涉及到许多社会因素

        对于嵌入式软件而言,除了具有通用软件的一般特性,同时还具有一些于嵌入式系统密切相关的特点:

        (1)软件受资源的限制,嵌入式系统资源优先,嵌入式软件必须尽可能精简,才能适应这种情况

        (2)开发难度大,嵌入式的运行环境和开发环境一般比较复杂,从而加大了它的开发难度。

(3)实时性和可靠性要求高。实时性主要靠软件层实现

        (4)要求固化存储,为了提高系统的启动速度、执行速度和可靠性,嵌入式系统中的软件一般固化在存储芯片或单片机中,而不是向通常的计算机系统那样,存储在磁盘等载体中。

4.1.3 嵌入式软件分类

按通常的分类方法,嵌入式软件可以分为三大类:系统软件应用软件支撑软件

        (1)系统软件:控制和管理嵌入式系统资源,为嵌入式系统应用提供支持的各种软件,如设备驱动程序、嵌入式操作系统、嵌入式中间件等;

        (2)应用软件:嵌入式系统中的上层软件,定义了嵌入式设备的主要功能和用途,并负责与用户交互。

        (3)支撑软件:辅助软件开发的工具软件,如系统分析涉及工具、在线仿真工具、交叉编译器、源程序模拟器和配置管理工具等。

4.1.4 嵌入式软件体系结构

1、无操作系统的情形

        无操作系统的嵌入式软件主要有两种实现方式:循环轮转前后台系统。

1)循环轮转方式

        循环轮转方式的基本思路是:把系统的功能分解为若干个不同的任务,然后把它们包含在一个循环语句中,按照顺序逐一执行。当执行完一轮循环后,又回到循环体的开头重新执行。如图所示:

        循环轮转方式的优点是简单、直观、开销小、可预测。软件的开发就是一个典型的基于过程的程序设计问题,可以按照自顶向下、逐步求精的方式,将系统要完成的功能划分为若干个小的功能模块。整条系统只有一条执行流程和一个地址空间,不需要任务之间的调度和切换,因此系统的管理开销很少。

        循环轮转方式的缺点是过于简单:所有的代码都必须按部就班地顺序执行,无法处理异步事件,缺乏并发处理的能力。另外,这种方案没有硬件上的时间控制机制,无法实现定时功能。

2)前后台系统

        前后台系统就是在循环轮转方式的基础上,增加了中断处理功能,如图所示:

        中断服务程序负责处理异步事件,这部分可以看出是前台程序。

        后台程序一般是一个无限的循环,负责掌管整个嵌入式系统软、硬件资源的分配、管理以及任务的调度。

2、有操作系统的情形

嵌入式操作系统在嵌入式应用中使用得越来越广泛,这种开发方式主要有以下三点优点:

        (1)提高了系统得可靠性;

        (2)提高了系统得开发效率,降低了开发成本

        (3)有利于系统得扩展和移植

嵌入式软件得体系结构图:

        最底层是嵌入式硬件,包括嵌入式微处理器、存储器和键盘、输入笔、LCD显示器等输入/输出设备。硬件之上是设备驱动层,负责与硬件直接打交道,并为上层软件提供所需得驱动支持。设备驱动层的上面是操作系统层,可分为基本部分和扩展部分,前者是操作系统的核心,负责整个系统的任务调度、存储管理、时钟管理和中断管理,后者则是系统为用户提供的一些扩展功能,包括网络、文件系统、图形用户界面GUI、数据库等。在操作系统上面,是中间件,再上面就是各种应用软件。

4.1.5 设备驱动层

        大多数的嵌入式硬件设备都需要某种类型的软件进行初始化和管理,这部分工作是由设备驱动层来完成的,它负责直接与硬件交互。对硬件进行管理和控制,并为上层软件提供所需的驱动支持。

1、板级支持包

        设备驱动层也称为板级支持包(BSP),包含了嵌入式系统中所有与硬件相关的代码。BSP的基本思想是将嵌入式操作系统与具体的硬件平台隔离开来,就是将所有与硬件相关的代码都封装起来,并向上提供一个虚拟的硬件平台,而操作系统就运行在这个虚拟的硬件平台上。

        对于不同的嵌入式操作系统,BSP的具体结构和组成也各不相同,一般来说,BSP主要包括两个方面的内容:引导加载程序BootLoader和设备驱动程序。

1)引导加载程序

        引导加载程序 BootLoader 是嵌入式系统加电后第一时间运行的软件代码。在桌面PC中的引导加载程序是由位于只读存储器ROM中的BIOS和位于硬盘的主引导记录中的BootLoader引导加载程序两部分代码组成的。

        简单来说,BootLoader就是在操作系统内核运行之前运行的一小段程序,通过这段程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境配置为一定的状态,以便为最终调用操作系统内核做好准备。

在嵌入式系统中,BootLoader的实现高度依赖于具体的硬件平台,具有如下基本功能:

        (1)片级初始化,片级初始化主要完成微处理器的初始化,包括设置微处理器的核心存储器和控制寄存器。片级初始化把微处理器从上电时的缺省状态逐步设置成系统所要求的工作状态。

        (2)板级初始化,通过正确地设置各种寄存器的内容来完成微处理器以外的其他设备的初始化,如初始化LCD显示设备、初始化定时器;

        (3)加载内核,将操作系统和应用程序的映像从Flash硬盘拷贝到系统的内核当中,然后跳转到系统内核的第一条指令处继续执行。

2)设备驱动程序

        驱动设备程序就是一组库函数,用来对硬件进行初始化和管理,并向上层软件提供良好的访问接口。

具有以下基本功能:

        (1)硬件启动:在开机上电或系统重启的时候,对硬件进行初始化

        (2)硬件关闭:将硬件设置成关机状态

        (3)硬件停用:暂停使用这个硬件

        (4)硬件启用:重新启用这个硬件

        (5)读操作:从硬件中读取数据

        (6)写操作:从硬件中写入数据

        除了普遍适用的功能,还可能有很多额外、特定的功能,在具体实现时,这些功能一般是用函数的形式来实现的,这些函数主要有两种组织结构,即分层结构和混合结构。

        所谓分层结构,就是把设备驱动程序当中的所有函数分为两种类型,一种是直接跟硬件交互,直接去操纵和控制硬件设备的,这些函数称为硬件接口;另一种是跟上层软件交互,作为上层软件的调用接口。分层结构的有点事:把所有与硬件相关的细节都封装在硬件接口当中,硬件升级时,只需要改动硬件接口当中的函数,而上层接口当中的函数不用做任何的修改。

        所谓混合结构,就是在设备驱动程序当中,上层接口与硬件接口的函数是混在一起、相互调用的,它们之间没有明确的层次关系。无论是分层结构还是混合结构,设备驱动程序的内部有任何变化,也不会影响到上层软件。

4.1.6 嵌入式中间件

        嵌入式中间件,就是在操作系统内核、设备驱动程序和应用软件之外的所有系统软件。嵌入式中间件的基本思路是:把原本属于应用软件层的一些通用的功能模块抽取出来,形成独立的一层软件,从而为运行在它上面的那些应用软件提供一个移植性好、相互通信的平台。

        嵌入式中间件可以分为不同的类型,如消息中间件、对象中间件、远程过程调用、数据库访问中间件、安全中间件等。

4.2 嵌入式操作系统概述

        嵌入式操作系统(EOS)是一种支持嵌入式系统应用的操作系统软件,它是嵌入式开发中极为重要的组成部分,通常包括与硬件相关的底层驱动软件、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器等。与通用操作系统相比,嵌入式操作系统在系统实时高效性、硬件的相关依赖性、软件固化态以及应用的专用性等方面具有较为突出的特点。

与通用操作系统一样,可以从两个方面来描述嵌入式操作系统的功能:

        (1)从软件开发的角度,可以把EOS看出是一种扩展机或者虚拟机,它把底层的硬件细节封装起来,为运行在它上面的软件(如中间件和各种应用软件)提供了一个抽象的编程接口。软件的开发不是直接在机器硬件的层面上进行的,而是在这个编程接口的层面上进行。

        (2)从系统管理的角度,可以把EOS看出系统资源的棺戮者,负责管理系统当中的各种软硬件资源,如处理器、内存、各种I/O设备、文件和数据等。

EOS除了具有通用操作系统的基本功能外,还有一些与嵌入式系统密切相关的特点:

        (1)其目标是为了完成某一项或有限功能,而非通用型的操作系统

        (2)在性能和实时性方面可能有严格的限制

        (3)能源、成本、可靠性通常是影响设计的重要因素

        (4)占用资源少,适合在有限存储空间运行

        (5)系统功能可根据需求进行裁剪、调整,以便满足最终产品的设计要求。

        一般来说,所有的操作系统都会有一个内核,所谓的内核就是指系统当中的一个组件,包含了OS的主要功能,即OS的各种特性及其相互之间的依赖关系。这些功能包括:任务管理、存储管理、输入/输出设备管理和文件系统管理。

        操作系统在计算机系统中处于系统软件的核心地位,是用户和计算机系统的界面。用户通过操作系统来使用计算机,每个程序都要通过操作系统获得必要的资源后才能执行,

一个计算机系统可以分为四个层次:硬件层、操作系统层、系统软件层和应用软件层

        每一层都表示一组功能和一个界面,表现为一种单向服务的关系,即上层的软件必须以事先约定的方式使用下一层软件或硬件提供的服务。

        为了提高计算机系统的效率,增强系统的处理能力,最大限度地提高资源利用率,现代操作系统采用了并行操作技术,使软件和因该你并行工作,因此以多道程序为基础地现代操作系统具有以下特征:

1、并发性

        并发两个或两个以上的事件在同一事件间隔内发生,对于程序而言,并发也就是多道程序在同一事件间隔内同时执行。宏观上看,似乎是同时进行的,但是在单处理器系统中,每时刻只能执行一道程序,因此微观上这些程序是交替执行的

2、共享性

        共享性就是资源共享,即计算机系统中的软、硬件资源供所有授权程序或用户共同使用。由于系统中的资源有限,当多道程序并发执行时,必然要共享系统中的软、硬件资源,因此,程序并发执行必然依赖于资源共享机制的支持

3、虚拟性

        所谓虚拟,就是采用某种方法把一个物理实体映射为一个或者多个逻辑实体。例如在多道程序系统中,只有一个CPU,每次只能执行一道程序,但是采用多道程序技术后,在一段时间内,宏观上看有多个程序在有哪些,似乎是多个CPU在运行各自的程序。也就是一个物理上的CPU虚拟为多个逻辑上的CPU,即虚拟处理器。类似的还有虚拟存储器、虚拟外围设备等。

与其他类型的操作系统相比,嵌入式操作系统具有以下特点:

        (1)体积小,嵌入式系统大多使用闪存作为存储介质,因此只能运行在有限的内存中,不能使用虚拟内存,中断的使用也受限制。

        (2)实时性,大多数嵌入式系统都是实时系统,而且多是强实时多任务系统,重点解决实时多任务调度算法和可调度性、死锁接触等问题

        (3)特殊的开发调试环境,一个完整的嵌入式系统集成开发环境一般包括编译/连接器、内核调试/跟踪器和集成图形界面开发平台,其中的集成图形界面开发平台包括编辑器、调试器、软件仿真器和监视器等。

4.2.1 嵌入式操作系统的分类

1、按提供的功能分类

        (1)单用户操作系统,主要特征是在一个计算机系统内,一次只能支持运行一个用户程序,此用户独占计算机系统的全部软、硬件资源

        (2)批处理系统,用户要把计算的问题、数据、作业说明书等一起交给系统操作员,系统操作员将一批算题输入计算机,然后由操作系统控制执行,这类操作系统又分为批处理单道系统和批处理多道系统。

        (3)实时操作系统,典型的实时操作系统包括过程控制系统、信息查询系统和事务处理系统,实时系统是较少人为干预的监督和控制系统。其软件依赖于应用的性质和实际使用的计算机类型。本质特征是事件驱动设计,即当接到某种类型的外部信息时,由系统选择相应的程序去处理。

        (4)分时操作系统,这是一种使用计算机为一组用户服务,使每个用户仿佛自己由一台支持自己请求服务的计算机的操作系统。分时操作系统的主要目的是对联机用户的服务和响应,具有同时性、独立性、及时性、交互性。分时操作系统和实时操作系统的主要差别在交互能力和响应时间上,分时系统交互性强,而实时系统响应时间要求高。

        (5)网络操作系统,提供网络通信和网络资源共享的操作系统称为网络操作系统,负责管理整个网络资源和方便网络用户的软件的集合。

        (6)分布式操作系统,分布式系统是由多台微机组成且满足如下条件的系统:系统中任意两台计算机可以通过通信交换信息;系统中的计算机无主次之分;系统中的资源供所有用户共享;一个程序可以分布在几台计算机上并行运行,互相协作完成一个共同的任务。

2、按系统的类型分类

        按照系统的类型,可以把嵌入式操作系统分为三大类:商用系统专用系统开源系统

        (1)商用系统,商业化嵌入式操作系统特点是功能强大、性能稳定、应用范围相对较广,辅助软件工具齐全

        (2)专用系统,一般不提供给应用开发者使用

        (3)开源系统,免费、开源、资源丰富

3、按响应时间分类

        按照系统对响应时间的敏感程度,可以把嵌入式操作系统分为两大类:实时操作系统和非实时操作系统

实时操作系统可以分为硬实时和软实时:

        (1)硬实时系统,系统对响应时间有严格的要求,绝不允许响应时间不能满足,否则可能会引起系统的奔溃或致命的错误

        (2)软实时系统,系统对响应时间有要求,如果响应时间不能满足,将带来额外的代价,不过这种代价可以接受

        非实时系统在响应时间上没有严格的要求,如分时操作系统,基于公平性原则,各个进程分享处理器,获得大致相同的运行时间,当一个进程在进行I/O操作时,会交出处理器,让其他的进程运行。

4、按软件结构分类

按照软件的体系结构,可以把嵌入式操作系统分为三大类:单体结构分层结构微内核结构

        它们之间地差别主要体现在两个方面:一是内核的设计,即在内核中包含了哪些功能组件;二是在系统中集成了哪些其他的系统软件(如设备驱动程序和中间件)

1)单体结构

        在单体结构的操作系统中,中间件和设备驱动程序通常就集成在系统内核当中,整个系统只有一个可执行文件,里面包含了所有功能组件,系统结构就是无结构,整个操作系统由一组功能模块组成,这些功能模块之间可以相互调用,如嵌入式Linux操作系统

        优点:性能较好,系统各模块之间可以互相调用,通信开销比较小

        缺点:操作系统具有体积庞大、高度集成和相互关联等特点,在系统剪裁、修改和调试等方面都较为困难。

2)分层结构

        在分层结构中,一个操作系统被划分为若干个层次,各个层次之间的调用关系是单向的,即某一层上的代码只能调用比它低层的代码,分层结构的操作也是只有一个大的可执行文件,其中包含设备驱动程序和中间件。这种结构要求在每个层次上都要提供一组API接口函数,会带来额外开销,影响系统规模和性能。

3)微内核结构

        微内核结构或者客户服务器结构的操作系统是指内核中将操作系统的大部分功能都剥离出去,只保留最核心的功能单元(如进程管理和存储管理),特点是内核非常小,大部分的系统功能都位于内核之外。

        在微内核操作系统中,新的功能组件可以被动态地添加进来,所以易于扩展、调试方便等特点,由于大部分地系统功能都被放置在内核之外,而客户单元和服务器单元地内存地址空间是相互独立,因此系统的安全性更高。还有一个优点是移植方便,但是运行速度慢一些,因为核内组件与核外组件之间的通信方式是消息传递,而不是直接的函数调用。

4.2.2 常见的嵌入式操作系统

        随着嵌入式系统发展,从早期的实模式进化到保护模式,从微内核技术进化到超微内核技术,从支持单处理器发展到支持多处理器、分布式和实时网络,嵌入式操作系统已经成为操作系统研究领域中的一个重要分支。目前,国内外已经有数十家公司在从事相关方面的研究,开发了数以百计的各具特色的嵌入式操作系统产品,其中比较有影响的系统包括: VxWorks、嵌入式 Linux、Windows CE、uC/OS-II 和 PalmOS 等。

1)Vx Works

        嵌入式实时操作系统,具有良好的可靠性和卓越的实时性,是目前嵌入式系统领域中使用最广泛、市场占有率最高的商业系统。

有以下几个功能模块组成:

        (1)高效的实时微内核:这是Vx Works的核心,包括基于优先级的任务调度、任务之间的通信、同步和互斥、中断处理、定时器和内存管理机制等

        (2)I/O处理系统:Vx Works提供了一个快速灵活的与ANSIC兼容的I/O系统,包括UNIX标准的缓存I/O和POSIX标准的异步I/O

        (3)文件系统:Vx Works提供了适合于实时应用的文件系统

        (4)网路处理模块:能与许多运行其他协议的网路进行通信,如TCP/IP

        (5)虚拟内存模块Vx VMI:主要用于对指定内存区的保护,以加强系统的安全性

        (6)板级支持包BSP:是系统用来管理硬件的功能模块,对各种板卡的硬件功能提供了统一的接口,由初始化和驱动程序两部分组成。

2)嵌入式Linux

        是对标准Linux进行小型裁剪处理后,可固化在存储器或单片机中,适合于特定嵌入式应用场合的专用Linux操作系统

特点包括:

        (1)高性能、可裁剪的内核:其独特的模块机制使用户可以根据自己的需要,实时地将缪写模块插入到内核或从内核中移走,很适合嵌入式系统的小型化的需要

        (2)完善的网络通信和文件管理机制:Linux支持所有标准的Internet网络协议,并且很容易移植到嵌入式系统当中

        (3)优秀的开发工具:嵌入式Linux提供了一套完整的工具链,利用GNU的gcc做编译器,用gdb、kgdb、xgdb做调试工具

        (4)免费、开放原码:Linux是开放源码的自由操作系统,用户可以根据自己的应用需要方便的对内核进行修改和优化。

        (5)广泛的硬件支持:支持x86、ARM、MIPS、PowerPC等多种体系结构

        (6)软件资源丰富:几乎每种通用程序在Linux上都能找到,减轻了开发工作量

3)Windows CE

        主要用在个人数字助理和智能电视等个人手持终端上,是一个基于优先级的多任务操作系统,提供了256个优先级别,但它并不是硬实时系统,基本内核需要至少200KB的ROM,支持Win 32 API子集,支持多种用户界面硬件,支持多种串行和网络通信技术

主要包含5个功能模块:

        (1)内核模块:支持进程和线程处理及内存管理等基本服务

        (2)内核系统调用接口模块:允许应用软件访问操作系统提供的服务

        (3)文件系统模块:支持DOS等格式的文件系统

        (4)图形窗口和事件子系统模块:控制图纸显示、并提供Windows GUI图形界面

        (5)通信模块:允许同其他的设备进程信息交换

4.3 任务管理

        在嵌入式系统中,往往需要执行多个程序,为了提高程序执行地效率,系统以任务为单元对程序进行管理。任务管理决定了嵌入式系统的实时性能,主要包括任务的创建、删除和调度等工作。

4.3.1 多道程序技术

        嵌入式操作系统分为两种类型:单道程序设计多道程序设计。单道程序设计,就是在操作系统当中,在任何时候只能有一个程序在运行;所谓多道程序设计,就是允许多个程序同时存在并运行,为了提高系统资源的利用率,普遍采用多道程序技术。

        在多道程序设计的环境下,允许多个程序同时运行,当一个程序在访问I/O设备时,会主动把CPU交出来,交由另一个程序去运行,这样提高了系统资源的使用效率。

        在多道程序设计的操作系统中,由于CPU和输入输出设备的使用是并行进行的,因此在总的执行时间上要明显少于单道系统

4.3.2 进程、线程和任务

在多道系统中,允许多个程序同时存在,各个程序之间是并发执行的,共享系统资源。

1、进程

一个进程就是正在运行的程序,一个进程至少应该包括以下几个方面的内容:

        (1)相应的程序

        (2)CPU上下文指程序在运行时,CPU中各种寄存器的当前值,包括:程序计数器,用于记录将要取出的指令的地址;程序状态字,用于记录处理器的运行状态信息;通用寄存器,用于存放数据或地址;段寄存器,用于存放程序中各个段的地址;栈指针寄存器,用于记录栈顶的当前位置。

        (3)一组资源系统:包括操作系统用来管理进程的数据结构、进程的内存地址空间、进程正在使用的文件等

进程有动态性、独立性、并发性三个特性

        (1)动态性。进程是一个正在执行的程序,而程序的运行状态是在不断变换的。当一个程序在运行的时候,每执行完一条指令,PC寄存器的值就会增加,指向下一条即将指向的指令。而CPU中用来存放数据和地址的那些通用寄存器,它们的值也在不断变化,此外,堆和栈的内容也在不断地变化,每当发生一次函数调用,就会在栈中分配一块空间,用来存放此次函数调用地参数和局部变量,当函数调用结束后,这块栈空间就会被释放掉。

        (2)独立性。一个进程是一个独立的实体,是计算机系统资源的使用单位。每个进程都有自己的运行上下文和内部状态,在它运行的时候独立于其他的进程

        (3)并发性。宏观上并发运行,微观上顺序运行。

2、线程

进程当中的一条执行流程,就是线程。

        (1)一个进程当中可以有多个线程

        (2)可以用线程来作为CPU的基本调度单位,使得各个线程之间可以并发地执行

        (3)对于同一个进程当中地各个线程来说,由于它们是运行在相同的资源平台上,因此它们可以共享该进程的各种资源,如内存地址空间、代码、数据、文件等等,这就使线程之间的通信变得非常方便。

        注:线程不能共享进程的所有资源,有小部分资源是不能共享的,每个线程都必须拥有各自独立的一份,这些资源包括CPU上下文(如程序寄存器、状态寄存器、通用寄存器和栈指针等)和栈。

3、任务

VXWorks的任务就是线程,在一些嵌入式Linux中,其任务就是进程。

4.3.3 任务的实现

1、任务的层次结构

        在多道程序的嵌入式操作系统中,同时存在多个任务,这些任务之间的结构一般为层状结构,存在着父子关系。当嵌入式内核刚刚启动的时候,只有一个任务存在,然后由该任务派生所有其他的任务。

2、任务的创建与终止

在一个嵌入式操作系统当中,任务的创建主要发生在以下三种情形:

        (1)系统初始化:当嵌入式内核在进行系统初始化的时候,一般都会创建一些任务

        (2)任务运行过程中:除了在系统初始化的时候会创建任务以外,当一个任务正在运行的时候,如果需要的话,也能使用相应的系统调用来创建新的任务,以帮助它完成自己的工作。

        (3)用户提出请求:在一些具有交互功能的嵌入式系统中,用户可以通过敲入命令或点击图标的方式,让系统启动一个新的任务。

        注:以上三种情形下,都能够创建一个新的任务,但是实际上只有一种创建任务的方法,也就是在一个已经存在的任务中,通过调用相应的系统调用函数来创建一个新的任务。

        在嵌入式操作系统中,任务的创建主要有两种可能的实现模型,即 fork/exec spawn ,两者既有联系也有区别

        fork/exec 模型源于 IEEE/ISO POSIX 1003.1 标准,而 spawn 模型是它派生出来的。这两种模型在创建任务的时候,过程非常相似,首先为新的任务分配相应的数据结构,存放其各种管理信息,然后为它分配内存空间,存放任务的代码和数据。当这个新任务准备就绪后,就可以启动其运行。

        两种模型的差别主要在于内存的分配方式。在 fork/exec 模型下,首先调用 fork 函数为新任务创建一份与父任务完全相同的内存空间,然后再调用 exec 函数装入新任务的代码,并用它来覆盖原有的属于父任务的内容。这个模型的优点是:对于新创建的子任务来说,如果需要的话,它可以从父任务那里继承代码、数据等各种属性。而 spawn 模型,摒弃了继承这一功能,在创建新任务的时候,直接为它分配一个新的全新的地址空间,然后将新任务的代码装入并运行。

3、任务的状态

        在多道程序系统中,任务是独立运行的实体,需要参与系统资源的竞争,只有在资源都得到满足的情形下,才能在 CPU 上运行。不同的嵌入式操作系统对任务状态的定义不尽相同,一般来说,都具有以下三种基本状态:

        (1)运行状态任务占用 CPU,并在 CPU上运行,显然,处于此状态的任务的个数必须小于或等于 CPU的数目。如果在系统当中只有一个 CPU 的话,那么在任何一个时刻,最多只能有一个任务处于运行状态

        (2)就绪状态任务已经具备了运行的条件,但是由于 CPU正忙,正在运行其他的任务,所以暂时不能运行,不过只要把CPU 分给它,它就能够立刻执行

        (3)阻塞状态也叫等待状态,任务因为正在等待某种事件的发生而暂时不能够运行,即使CPU已经空闲,它还是不能运行。

        在一定条件下,任务会在不同的状态之间来回切换,对于任务的三种状态,可以有四种转换关系

        (1)运行 -> 阻塞:任务由于等待某个事件被阻塞起来。如一个任务正在 CPU上运行,这是它需要输入一个字符,由于 CPU的运行速度远远高于 I/O设备的处理速度,因此操作系统不会允许该任务继续占用 CPU,在那里空等,而是把它变成阻塞状态,然后调用其他的任务去运行。

        (2)运行 -> 就绪:一个任务正在 CPU上运行,这时由于种种原因(如该任务的时间片用完,或另一个高优先级任务就绪),调度器选择了另一个任务去运行。这样对于当前任务来说,就从运行状态变成了就绪状态。

        (3)就绪 -> 运行:处于就绪状态的任务被调度器选中去运行

        (4)阻塞 -> 就绪:一个任务曾经因为等待某个事件而被阻塞起来,如果它等待的事件发生了,那么该任务就从阻塞状态变成了就绪状态,从而具备了继续运行的条件。

4、任务控制块

        任务控制块(TCB)是操作系统中的重要概念,任务管理就是通过对各个任务的 TCB 的操作来实现的

        TCB,就是在操作系统当中,用来描述和管理一个任务的数据结构。系统为每个任务都维护了一个相应的 TCB,用来保存该任务的各种相关信息。TCB的内容主要包括任务的管理信息、CPU上下文信息和资源管理信息。

        (1)任务的管理信息。包括任务的标识ID、任务的状态、任务的优先级、任务的调度信息、任务的时间统计信息、各种队列指针等。

        (2)CPU上下文信息。指CPU中各寄存器的当前值,包括通用寄存器、PC寄存器、程序状态字、栈指针等。在实际的嵌入式系统中,CPU上下文信息不一定直接存放在 TCB 当中,而是存放在任务的栈中,可以通过相应的栈指针来访问。

        (3)资源管理信息。如果在操作系统当中,任务表示的是进程,则还应包含一些资源管理方面的信息,如段表地址、页表地址等存储方面的信息;根目录、文件描述字等文件管理方面的信息

        在嵌入式操作系统中,可以用 TCB 来描述任务的基本情况以及它的运行变化过程,把 TCB 看成是任务存在的唯一标志。当需要创建一个新任务的时候,就为它生产一个 TCB,并初始化这个 TCB 的内容,当需要中止一个任务的时候,只要回收它的 TCB即可。而对于任务的组织和灌流,也可以通过对它们的 TCB 的组织和管理来实现。

5、任务切换

        一个任务在 CPU 上运行,这时由于某种原因,系统决定调度了另一个任务区运行。那么在这种情况下,就要进行一次任务切换,把当前任务的运行上下文保存起来,并恢复新任务的上下文。

任务切换通常具有如下基本步骤:

        (1)将处理器的运行上下文保存在当前任务的 TCB 当中;

        (2)更新当前任务的状态。从运行状态变成就绪状态或阻塞状态

        (3)按照一定的策略,从所有处于就绪状态的任务中选择一个去运行

        (4)修改新任务的状态,从就绪状态变成运行状态

        (5)根据新任务的 TCB 内容,恢复它的运行上下文环境

6、任务队列

        操作系统来维护一组队列,用来表示系统当中所有任务的当前状态,不同的状态用不同的队列来表示。如处于运行状态的所有任务构成了运行队列,处于就绪状态的所有任务构成看就绪队列,而对于处于阻塞状态的任务,则要根据它们阻塞的原因,分别构成相应的阻塞队列。然后,对于系统当中的每一个任务,根据它的状态把它的 TCB 加入到相应的队列当中去。如果一个任务的状态发生变化,如从运行状态变成就绪状态,或者从阻塞状态变成就绪装填,这时,就要把它的 TCB 从一个状态队列中脱离出来,加入到另一个队列当中去。

4.3.4 任务的调度

        在多道程序操作系统中,经常会出现多个任务同时去竞争CPU的情形,对于就绪队列中的任务,应该选择哪一个去运行,在操作系统中,负责做出这个选择的一部分程序,就被称为调度器,而调度器在决策过程中所采用的算法,就被称为调度算法。如果从资源管理的角度来看,也可以把调度器看成是CPU这个资源的管理者。

1、任务调度主要概念

1)调度时机

        (1)当一个新的任务被创建时,需要做出一个调度决策,是立即执行这个新任务还是继续执行父任务

        (2)当一个任务运行结束时,它就不再占用CPU,这是调度器必须做出一个决策,从就绪队列中选择某个任务区运行。如果此时没有任务处于就绪状态,系统一般会调度一个特殊的空闲任务。

        (3)当一个任务由于I/O操作、信号量或其他原因被阻塞时,也必须另选一个任务运行。

        (4)当一个I/O中断发生时,表明某个I/O操作已经完成,而等待I/O操作的任务将从阻塞状态变为就绪状态,此时需要做出一个调度决策,是立即执行这个新就绪的任务,还是继续执行刚才被中断的任务。

        (5)当一个时钟中断发生时,表明一个时钟节拍已经结束,这时可能会唤醒一些延时的任务,使它们变为就绪状态,也可能会发生当前任务的时间片已用完,从而把它变为就绪状态,这些情形下,也需要调度器来重新调度。

2)调度方式

主要有两种方式:不可抢占调度可抢占调度

(1)不可抢占方式

        如果一个任务被调度程序选中,就会一直运行下去,知道因为某种原因阻塞,或者主动地交出CPU的使用权。在不可抢占的调度方式下,当出现调度时机当中的前三种情形时,即新任务创建、任务运行结束及任务被阻塞,都有可能会发生调度。而对于第四种和第五种情形,即发生各种中断的时候,虽然也会有中断处理程序,但是它并不会去调用调度程序。

(2)可抢占方式:

        当一个任务正在运行时,调度程序可以去打断它,并安排另外的任务去运行。实时操作系统大都采用了可抢占的调度方式,使一些比较重要的关键任务能够打断那些不太重要的非关键任务的执行,以确保关键任务的截止时间能够得到满足。

(3)调度算法性能指标和分类

        任务调度的第三个问题是调度算法的性能指标,即如何来评价一个调度算法的好坏,这些指标包括:

        响应时间:调度器为一个就绪任务进行上下文切换时所需的时间,以及任务在就绪队列中等待的时间

        周转时间:一个任务从提交到完成所经历的时间

        调度开销:调度器在做出调度决策时所需要的时间和空间开销

        公平性::大致相当的两个任务所得到的CPU时间也应该大致相同的

        均衡性:要尽可能使整个系统的各个部分(CPU、I/O)都忙起来,提高系统资源的使用效率

        吞吐量:单位时间内完成的任务数量

2、任务调度算法

1)先来先服务算法

        先进先出算法,基本思想就是按照任务到达的先后次序来进行调度,是一种不可抢占的调度方式。

2)短作业优先算法

        基本思想是各个任务在开始执行前,必须事先预计好它的执行时间,然后调度算法根据这些预计时间,从中选择用时较短的任务优先执行。

3)时间片轮转算法

        基本思想是把系统当中所有就绪任务按照先来先服务的原则,排成一个队列,然后,在每次调度的时候,把处理器分派给队列当中的第一个任务,让它去执行一小段CPU时间,或者叫时间片。优点是:公平性,各个就绪任务平均分配CPU的使用时间。活动性,每个就绪任务都能一直保持着活动性。

4.3.5 任务间的同步与互斥

1、任务之间的关系

        在一个嵌入式应用系统中往往包含多个任务,它们在系统的硬件平台和操作系统提供的软件平台上运行,这些任务之间主要有以下几种关系:、

        (1)相互独立:任务之间没有任何的关联关系,互不干预。唯一的相关性就是它们都需要去竞争CPU资源

        (2)任务互斥:除了CPU之外,这些任务还需要共享其他的一些硬件和软件资源,而这些资源由于种种原因,在某一时刻只能允许一个或者几个任务去访问,因此当这些任务在访问资源的时候可能会相互阻碍

        (3)任务同步:任务之间存在着某种依存关系,需要协调彼此的运行步调

        (4)任务通信:任务之间存在着协作与分工,需要相互传递各种数据和信息,才能完成各自的功能

2、任务互斥

        把一个任务在运行过程中所作的各种事情分为两类,第一类是任务内部的计算或其他的一些事情,这些事情肯定不会导致竞争条件的出现;第二类是对共享资源的访问,这些访问可能会导致竞争条件的出现将相应的那一部分程序称为临界区,把需要互斥访问的共享资源称为临界资源。

互斥访问的四个条件:

        (1)在任何时候最多只能有一个任务位于它的临界区当中

        (2)不能事先假定CPU的个数和系统的运行速度

        (3)如果某一个任务没有位于它的临界区当中,它不能妨碍其他的任务去访问临界资源

        (4)任何一个任务进入临界区的请求必须在有限的时间内得到满足,不能无限期地等待

3、任务互斥的解决方案

 1)关闭中断法

        为了实现任务之间的互斥,最简单的办法就是把中断关掉,具体来说,当一个任务进入它的临界区之后,首先把中断关闭掉,然后就可以去访问共享资源,当它从临界区退出时,再把中断打开。

        缺点:这种方法有一定的风险,当任务把中断关闭后,如果由于种种原因不能及时地打开中断,那么整个系统就可能陷入崩溃地状态。其次,这种方法地效率不高,关闭所有的中断,所有的任务都被阻止了,不论是竞争对手,还是毫不相干的任务,都被拒之门外,无法运行。

        主要用在操作系统的内核当中,使内核在处理一些关键性的敏感数据时,不会受到其他任务的干扰。

2)繁忙等待法

        基本思想:当一个任务想要进入它的临界区时,首先检查一下是否允许它进入,若允许,就直接进入,反之,就在循环地等待。

4、信号量

基本思想是使用一种新的变量类型,即信号量来记录当前可用资源的数量。

在信号量的具体实现上,有两种不同的方式:

        (1)方式一:要求信号量的取值必须大于或等于0,如果信号量的值等于0,表示当前已经没有可用的空闲资源;如果信号量的值大于0,则该值就代表了当前可用的空闲资源的数量

        (2)方式二:信号量的取值可正可负,如果是正数或0,其含义与方式一是相同的;如果是负数,则它的绝对值就代表正在等待进入临界区的任务个数。

        信号量是由操作系统来维护的,任务不能直接去修改它的值,只能通过初始化和两个标准源于(即P、V原语)来对它进行访问。

        P原语,主要功能是申请一个空闲的资源,把信号量的值减1。如果成功的话,就退出原语;如果失败的话,这个任务就会被阻塞起来。

        V原语,主要功能是释放一个被占用的资源,把信号量的值加1,如果发现有被阻塞的任务,就从中选择一个把它唤醒。

        采用信号量来实现任务之间的互斥,优点有两个:一是可以设置信号量的计数值,从而允许多个任务同时进入临界区;二是当一个任务暂时无法进入临界区时,它会被阻塞起来,从而让出CPU给其他的任务。

5、任务同步

        要实现任务之间的同步,可以使用信号量机制,通过引入P、V操作来设定两个任务在运行时的先后顺序。在具体实现上,一般把信号量的初始值设置成N,N大于或等于0,然后再一个任务的内部使用V原语,增加资源的个数;而在另一个任务的内部使用P原语,减少资源的个数,从而实现这两个任务之间的同步关系。

6、死锁

        在一个任务当中,每个任务都占用着若干个资源,同时又在等待其他任务所占用的资源,从而造成所有任务都无法进展下去的现象,这种现象称为死锁,这一组相关的任务又称为死锁任务,在死锁任务下,每个任务都动弹不得,既无法运行,也无法释放所占用的资源,它们互为因果、相互等待。

死锁的产生有四个必要条件,只有当这四个条件同时成立时,才会出现死锁。

        (1)互斥条件:在任何时刻,每一个资源最多只能被一个任务所使用

        (2)请求和保持条件:任务在占用若干个资源的同时又可以请求新的资源

        (3)不可抢占条件:任务已经占用的资源不会被强制性拿走,而必须由该任务主动释放

        (4)环路等待条件:存在一条由两个或多个任务所组成的环路链,其中每一个任务都在等待环路链中下一个任务所占用的资源。

除了资源的竞争外,PV操作使用不当也会引起死锁。

7、信号

        任务间同步的另一种方式是异步信号。在两个任务之间,可以通过相互发送信号的方式,来协调它们之间的运行步调。

        信号,指的是系统给任务的一个指示,表明某个异步事件已经发生了,该事件可能来自外部(如其他的任务、硬件或定时器),也可能来自内部(如执行指令出错)。

信号机制与中断处理机制非常相似,但又各有不同,它们的相同点是:

        (1)都具有中断性:在处理中断和异步信号时,都要暂时地中断当前任务的运行

        (2)都有相应的服务程序

        (3)都可以屏蔽相应;外部硬件中断可以通过相应的寄存器操作来屏蔽,任务也能够选择不对异步信号进行响应

        (4)中断是由硬件或特定的指令产生,而信号是由系统调用产生;

        (5)中断触发,硬件会根据中断向量找到相应的处理程序去执行,而信号则通过发送信号的系统调用来触发,但是系统不一定马上对它进行处理

        (6)中断处理程序是在系统内核的上下文运行,是全局的;而信号处理程序是在相关任务的上下文中运行,是任务的一个组成部分。

4.3.6、任务间通信

        任务间通信是指任务之间为了协调工作,需要相互交换数据和控制信息。任务之间的通信可以分为两种类型:

        (1)低级通信:只能传递状态和整数值等控制信息。如,用来实现任务间同步与互斥的信号量机制和信号机制都是一种低级通信方式,优点是速度快,缺点是传送的信息量非常少,如果要传递较多信息,就得进行多次通信。

        (2)高级通信:能够传送任意数量的数据,主要包括三类:共享内存、消息传递、管道

1、共享内存

        共享内存是指各个任务共享它们地址空间当中的某些部分,在此区域内,可以任意读写和使用任意的数据结构,把它看成一个通用的缓冲区。一组任务向共享内存中写入数据,另一组任务从中读出数据,通过这种方式来实现它们之间的信息交换。

        在使用共享内存来传送数据时,通常要与某种任务间互斥机制结合起来,以免发送竞争条件的现象,以确保数据传送的顺利进行。

2、消息传递

        消息是内存空间中一段长度可变的缓冲区,其长度和内容均有用户定义。

        消息传递指的是任务与任务之间通过发送和接收消息来交换信息

        消息机制由操作系统来维护,包括定义寻址方式、认证协议、消息的数量等。一般提供两个基本操作:send操作,用来发送一条消息;receive操作,用来接收一条消息。

        如果两个任务想要利用消息机制来进行通信,它们首先要在两者之间建立一个通信链路,然后就可以使用send和receive操作来发送和接收消息。

任务之间的通信可以分为直接通信和间接通信两种

        (1)直接通信,该方式下,通信双方必须明确知道与之通信的对象,采用下面的通信原语:

        【1】send(P,message),发送一条消息给任务P

        【2】receive(Q,message),从任务Q那里接收一条消息,如果没有收到消息,可以阻塞起来等待消息的到来,也可以立即返回

在通信双方之间存在一条通信链路,该链路有如下特征:

        【1】通信链路是自动建立的,由操作系统来维护

        【2】每条链路只涉及一对相互通信的任务,每队任务之间仅存在一条链路

        【3】通信链路可以是单向或双向的

        (2)间接通信,该通信方式下,通信双方不需要指出消息的来源或去向,而是通过共享的邮箱来发送和接收消息,每个邮箱都有一个唯一的标识,采用下面的通信原语:

        【1】send(A,message),发送一条消息到邮箱A

        【2】receive(A,message),从邮箱A接收一条消息

间接通信的特点:

        【1】对于一对任务,只有当它们共享一个公共邮箱时才能进行通信

        【2】一个邮箱可以被多个任务访问,每队任务也可以使用多个邮箱来通信

        【3】通信可以是单向或双向的

3、管道

        管道通信由UNIX首创,由于其有效性,后来的一些系统相继引入了管道技术。管道通信以文件系统为基础,所谓管道即连接两个任务之间的一个打开的共享文件,专用于任务之间的数据通信,一端写入数据流,一端按照先进先出的顺序读出数据流

4.4 存储管理

4.4.1 存储管理概述

通常,在设计存储管理的时候,需要考虑如下的一些因素:

        【1】硬件条件,例如是否有存储单元MMU

        【2】实时性要求,是硬实时、软实时还是分时系统

        【3】系统规模大小、复杂程序、性能要求

        【4】可靠性要求,是否需要内存保护

1、内存保护

        包含两个方面的内容:一是防止地址越界,每个应用程序都有自己独立的地址空间,当一个应用程序要访问某个内存单元时,由硬件检查该地址是否在限定的地址空间内,如果不是的话就要进行地址越界处理二是防止操作越权,对于允许多个应用程序共享的某块存储区域,每个应用程序都有自己的访问权限,如果违反了权限规定,则要进行操作越权处理。

2、实时性要求

为了确保系统的实时性,在内存管理方面需要考虑如下因素:

        (1)速度快:存储管理方面的开销不能太大

        (2)确定性:对于每一项工作都要有明确的实时约束,必须在某个限定的时刻之前完成。

4.4.2 实模式与保护模式

1、实模式方案

        也成为内存的平面使用迷失,在这种存储管理方式下,系统将关闭MMU或者根本没有MMU

主要特点:

        (1)不划分系统空间和用户空间,整个系统只有一个地址空间,即物理内存地址空间,应用程序和系统程序都能直接对所有的内存单元进行随意的访问,无需进行地址映射

        (2)操作系统的内核与外围应用程序之间不再有物理边界,在编译链接后,两者通常被集成在统一系统文件中

        (3)系统中所说的任务或进程,实际上全都是内核线程,这些线程来说,只有允许上下文和栈是独享的,其他资源都是共享的

        优点是简单、性能好;缺点是没有存储保护、安全性差

2、保护模式方案

指的是在处理器中必须要有MMU硬件并启用它

主要特点:

        (1)系统内核和用户程序都有各自的独立的地址空间,操作系统和MMU共同合作,完成逻辑地址到物理地址的映射

        (2)具有存储保护功能,每个应用程序只能访问自己的地址空间,不能去破环操作系统和其他应用程序的代码和数据,对于共享的内存区域,也必须按照规定的权限规则来访问

4.4.3 分区存储管理

1、固定分区存储管理

        基本思路:各个用户分区的个数、位置和大小一旦确定,就固定不变。

        在系统启动时,由管理员来手工划分出若干个分区,并确定各个分区的起始地址的大小等参数,然后,在系统的整个运行期间,这些参数就固定下来,不再改变,另外,为了满足不同程序的存储需要,各个分区的大小可以是相等的,也可以是不相等的。

2、可变分区存储管理

        基本思路:分区不是预先划分好的固定区域,而是动态创建的,在装入一个程序时,系统将根据它的需求和内存空间的使用情况决定是否分配。

        在系统生成后,操作系统会占用内存的一部分空间,这一般是放在内存地址的最低端,其余的空间则成为一个完整的大空闲区。当一个程序要求装入内存运行时,系统会从这个空闲区当中划出一块来,分配给它,当程序运行结束后会释放所占用的存储区域。随着一系列的内存分配和回收,原来的一整块的大空闲区就会形成若干个占用区和空闲区相间的布局。

4.4.4 地址映射

        地址映射也叫地址重定位,涉及两个基本概念:物理地址和逻辑地址

        (1)物理地址也叫内存地址、绝对地址或实地址。也就是说,把系统内存分割成很多个大小相等的存储单元,如字节或字,每个单元给它一个编号,这个标号就成为物理地址。物理地址的集合就称为物理地址空间,或者内存地址空间,是一个一维的线性空间。假设内存大小为256MB,那么它的内存地址空间就是从0x0到0x0FFFFFFF。

        (2)逻辑地址也叫相对地址或虚地址,也就是说,用户的程序经过汇编或编译后形成目标代码,而目标代码通常采用的就是相对地址的形式。其首地址为0,,其余指令中的地址都是相对于这个首地址来编址的。

        为了保证CPU在执行指令的时候,可以正确地访问内存单元,需要将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址,这个过程就称为地址映射。地址映射是由存储管理单元MMU来完成的

        当一条指令在CPU当中执行时,它可能需要去访问内存,因此就发送一个逻辑地址给MMU,MMU负责把这个逻辑地址转换为相应的物理地址,并根据这个物理地址去访问内存。

地址映射主要有两种方式:静态地址映射和动态地址映射

1、静态地址映射

        静态地址映射的基本思路是:当用户程序被装入内存时,直接对指令代码进行修改,一次性地实现逻辑地址到物理地址地转换。

        具体实现时,在每一个可执行文件中,要列出各个需要重定位地地址单元的地址,然后由一个加载程序来完成装入及地址转换的过程。这种方式实现起来很简单,不要要任何硬件方面的支持,但是它的缺点是,程序一旦装入内存后,就不能再移动

2、动态地址映射

        动态地址映射的基本思路是: 当用户程序被装入内存时,不对指令代码做任何的修改。而是在程序的运行过程中,当它需要访问内存单元的时候,再进行地址转换。

        具体实现时,为了提高效率,该转换工作一般是由硬件的地址映射机制来完成。通常的做法是设置一个基地址寄存器,或者叫重定位寄存器。当一个任务被调度运行时,就把它所在分区的起始地址装入到这个寄存器中。然后,在程序的运行过程中,当需要访问某个内存单元时,硬件就会自动地将其中的逻辑地址加上基地址寄存器当中的内容,从而得到实际的物理地址,并按照这个物理地址去访问。

4.4.5 页式存储管理

1、基本原理

        分区存储管理的一个特点是连续性,每个程序都分得一片连续的内存区域。这种连续性将导致碎片问题,包括固定分区中的内碎片和可变分区中的外碎片。为了解决这些问题,提出了页式存储管理方案。它的基本出发点是打破存储分配的连续性,使一个程序的逻辑地址空间可以分布在若干个离散的内存块上,从而达到充分利用内存,提高内存利用率的目的。

        页式存储管理的基本思路是:一方面,把物理内存划分为许多个固定大小的内存块,称为物理页面,或页框另一方面,把逻辑地址空间也划分为大小相同的块,称为逻辑页面,或简称为页面。页面的大小要求是 2^n,一般在 512B 到 8KB 之间。当一个用户程序被装入内存时,不是以整个程序为单位,把它存放在一整块连续的区域,而是以页面为单位来进行分配。对于一个大小为N个页面的程序,需要有 N个空闲的物理页面把它装进来,当然,这些物理页面不一定是连续的。

2、数据结构

在页式存储管理中,最主要的数据有两个

        (1)页表:页表给出了任务的逻辑页面号与内存中的物理页面之间的对应关系

        (2)物理页面表用来描述内存空间中各个物理页面的使用分配情况。在具体实现上,可以采用位示图或空闲页面链表等方法

3、内存的分配与回收

内存的分配过程是这样的:

        (1)对于一个新来的任务,计算它所需要的页面数 N。然后查看位示图,看是否还有 N个空闲的物理页面。

        (2)如果有足够的空闲物理页面,就去申请一个页表,其长度为 N,并把页表的起始地址填入到该任务的任务控制块 TCB 当中。

        (3)分配 N个空闲的物理页面,把它们的编号填入到页表中。这样,就建立了逻辑页面与物理页面之间的对应关系。

        (4)修改位示图,对刚刚被占用的那些物理页面进行标记。当一个任务运行结束,释放了它所占用的内存空间后,需要对这些物理页面进行回收,并对位示图的内容进行相应的修改。

4、地址映射

地址映射的基本思路是:

        (1)逻辑地址分析:对于给定的一个逻辑地址,找到它所在的逻辑页面,以及它在页面内的偏移地址;

        (2)页表查找:根据逻辑页面号,从页表中找到它所对应的物理页面号:

        (3)物理地址合成:根据物理页面号及页内偏移地址,确定最终的物理地址.

4.4.6 虚拟存储管理

        在操作系统的支持下,MMU 还提供虚拟存储功能。即使一个任务所需要的内存空间超过了系统所能提供的内存空间,也能够正常运行。

1、程序局部性原理

        程序的局部性原理,指的是程序在执行过程中的一个较短时期内,它所执行的指令和访问的存储空间,分别局限在一定的区域内。这可以表现在时间和空间两个方面:

        (1)时间局限性:一条指令的一次执行和下一次执行,一个数据的一次访问和下一次访问,都集中在一个较短的时期内;

        (2)空间局限性:如果程序执行了某条指令,则它相邻的几条指令也可能马上被执行:如果程序访问了某个数据,则它相邻的几个数据也可能马上被访问。

2、虚拟页式存储管理

        虚拟页式存储管理就是在页式存储管理的基础上,增加了请求调页和页面置换的功能。

        它的基本思路是:当一个用户程序需要调入内存去运行时,不是将这个程序的所有页面都装入内存,而是只装入部分的页面,就可以启动这个程序去运行。在运行过程中,如果发现要执行的指令或者要访问的数据不在内存当中,就向系统发出缺页中断请求,然后系统在处理这个中断请求时,就会将保存在外存中的相应页面调入内存,从而使该程序能够继续运行。

4.5 设备管理

        在嵌入式系统中,存在各种类型的输入/输出设备。既包括键盘、触摸屏、液晶显示器等人机交互设备,也包括 D/A、A/D 转换器、电机等专用设备。一个输入/输出单元通常是由两个部分组成的:一个是机械部分,即 I/O 设备本身;另一个是电子部分,即设备控制器或设备适配器。

4.5.1 设备管理基础

        设备适配器的功能是完成设备与主机之间的连接和通信。也就是说,输入/输出设备本身并不直接跟 CPU 打交道,而是通过它的设备控制器来跟 CPU 打交道。在每个设备控制器当中,都会有一些寄存器,用来与 CPU 进行通信,包括控制寄存器、状态寄存器和数据寄存器等。通过往这些寄存器当中写入不同的值,操作系统就可以命令设备去执行发送数据、接收数据、打开、关闭等各种操作。

        那么 CPU 如何来访问设备控制器当中的这些寄存器呢? 如果是访问普通的内存单元,那么很简单,只要指明这个内存单元的地址即可。但是现在要访问的是一些硬件寄存器,因此必须设计出相应的解决办法。主要有三种:I/O 独立编址、内存映像编址和混合编址。

        (1)I/O 独立编址:基本思路是: 对于各种设备控制器当中的每一个寄存器,分配一个唯一的 I/O端口编号,也叫 I/O 端口地址,然后用专门的 I/O 指令来对这些端口进行操作。这些端口地址所构成的地址空间是完全独立的,与内存的地址空间没有任何关系。采用这种独立编址的方法,其优点是:I/O 设备不会去占用内存的地址空间,而且在编写程序的时候,很容易区分内存访问和 I/O 端口访问,因为对于不同的操作来说,它们的指令形式是不一样的。

        (2)内存映像编址:内存映像编址的基本思路是:把各种设备控制器当中的每一个寄存器都映射为一个内存单元,这些内存单元专门用于输入/输出操作,而不能作为普通的内存单元来使用,不能往里面存放一些与输入/输出无关的数据。

        (3)混合编址:混合编址的基本思路就是把以上两种编址方法混合在一起。具体来说,对于设备控制器当中的寄存器,采用独立编址的方法,每一个寄存器都有一个独立的 IO 端口地址;而对于设备的数据缓冲区,则采用内存映像编址的方法,把它们的地址统一到内存地址空间当中。

4.5.2 I/O控制方式

I/O设备控制方式有三种:程序循环检测、中断驱动、直接内存访问

1、程序循环检测

        程序循环检测方式的基本思路是:在程序当中,通过不断地检测I/O设备的当前状态,来控制一个I/O操作的完成。具体来说,在进行I/O操作之前,要循环地去检测该设备是否已经就绪。如果是,就向控制器发出一条命令,启动这一次的I/O操作。然后,在这个操作的进行过程中,也要循环地去检测设备的当前状态,看它是否已经完成。总之,在 I/O操作的整个过程中,控制I/O 设备的所有工作都是由 CPU来完成的。这种方式也称为是繁忙等待方式或轮询方式。它的缺点主要是:在进行一个I/O操作的时候,要一直占用着 CPU,这样就会浪费 CPU 的时间。

2、中断驱动

        中断驱动方式的基本思路是:当一个用户任务需要进行I/O操作时,会去调用相应的系统调用函数,由这个函数来发起I/O操作,并将当前任务阻塞起来,然后调度其他的任务去使用 CPU。当所需的I/O操作完成时,相应的设备就会向CPU 发出一个中断,系统在中断处理程序当中,如果发现还有数据需要处理,就再次启动I/O操作。在中断驱动的控制方式下,数据的每一次读写还是通过 CPU 来完成,只不过当I/O设备在进行数据处理时,CPU 不必在那里等待,而是可以去执行其他的任务。

3、直接内存访问

        直接内存访问方式的基本思路是:让 DMA 控制器来代替 CPU,完成输入/输出设备与内存之间的数据传送,从而释放 CPU 时间,去运行其他的任务。

4.5.3 I/O软件

        低层软件面向硬件,与硬件特性密切相关,它把硬件和上层的软件隔离开来。较高层的软件是面向用户的,负责向用户提供一个编程接口。一般来说,这个层次结构可以分为四层:中断处理程序、设备驱动程序、设备独立的I/O软件和用户空间的I/O软件

1、中断处理程序

        中断处理程序与设备驱动程序密切配合,来完成特定的 IO 操作。当一个用户程序需要某种I/O服务时,它会去调用相应的系统调用函数,而这个函数又会去调用相应的设备驱动程序。然后,在驱动程序中会启动I/O操作,并且被阻塞起来。直到这个 IO 操作完成,之后将产生一个中断,并跳转到相应的中断处理程序。然后在中断处理程序中,将会唤醒被阻塞的驱动程序。至于阻塞和唤醒的具体实现,可以采用各种任务间通信的方式,如 P、V 原语。

        在中断处理过程中,还需要执行如下指令,如保存 CPU 的运行上下文、为中断服务子程序设置一个运行环境、向中断控制器发出应答信号以及执行相应的中断服务子程序等,这些都需要一定的时间开销。

2、设备驱动程序

        设备驱动程序是直接同I/O设备交互,直接对它们进行控制的软件模块。设备驱动程序的基本任务就是接收来自于上层 I/O 软件的抽象请求,并且去执行这个请求。例如,抽象的读操作、写操作、设备的初始化操作等。上层的 I/O 软件通过这些抽象的函数接口与设备驱动程序打交道,这些接口是标准的、稳定不变的。而硬件设备的具体细节被封装在设备驱动程序里面。这样,即使硬件设备发生了变化,只要更新相应的设备驱动程序即可,不会影响到上层软件对它的使用。

3、设备独立的I/O软件

        在设备驱动程序的上面,是设备独立的I/O软件。它是系统内核的一部分,主要任务是实现所有设备都需要的一些通用的I/O功能,并向用户级的软件提供一个统一的访问接口。具体来说,在这个层面上实现的功能主要有: 设备驱动程序的管理、与设备驱动程序的统一接口、设备命名、设备保护、缓冲技术、出错报告以及独占设备的分配和释放。

4、用户空间的I/O软件

        通常大部分的 I/O 软件都是包含在操作系统当中,是操作系统的一部分,但也有小部分的 IO 软件,它们运行在系统内核之外。这主要可以分为两种:

        (1)与用户程序进行链接的库函数。例如,在 C 语言中与I/O有关的各种库函数不过,对于这些库函数,它们在具体实现的时候,其实是把传给它们的参数再往下传递给相应的系统调用函数,然后由后者来完成实际的I/O操作。

        (2)完全运行在用户空间当中的程序。例如,Spooling 技术是在多道系统中,一种处理独占设备的方法。

4.6 文件系统

        所谓的文件系统,就是操作系统中借以组织、存储、命名、使用和保护文件的一套管理机制。

4.6.1 嵌入式文件系统概述

        操作系统基本上以文件的形式管理磁盘及其他存储设备上的数据结构,负责管理和存储文件信息的软件称为文件管理系统,简称文件系统。文件系统由三部分组成:与文件管理有关的软件、被管理文件以及实施文件管理所需的数据结构。文件系统是对文件存储器空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。其主要功能是建立文件、存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。

        常见的一些嵌入式文件系统包括:

        (1)FAT : FAT 文件系统是最常用的文件系统之一,最早于 1982年应用在 MS-DOS 操作系统当中。许多的嵌入式操作系统都支持 FAT 文件系统,如 VxWorks、ONX、Windows CE 等。为了与PC 机文件系统兼容,在嵌入式系统设计中一般使用标准的 FAT12/16/32 文件系统;

        (2)NFS : 网络文件系统,基于远程过程调用(RPC) 和扩展数据表示(XDR)。它可以将外部设备安装在文件系统中,就好像是一个本地的文件分区,从而可以实现对网络文件的快速、无缝的共享:

        (3)FFS : 用于 Flash 存储器的文件系统;DosFS: 用于实时条件下的块设备(磁盘) 访问,并且与 MS-DOS 文件系统兼容:。RawFS: 提供了一个简单的“生”的文件系统,它的基本思路是把整个磁盘视为一个巨大的文件;

        (4)TapeFS: 用于磁带设备,在磁带上不使用标准的文件或目录结构。其基本思路是把整个磁带卷视为一个巨大的文件;

        (5)CdromFS: ISO 9660 标准文件系统,用于 CD-ROM 数据的访问。

4.6.2 文件和目录

1、文件的基本概念

        当一个文件被创建时,必须给它指定一个名字,因为用户就是通过文件名来访问这个文件的。文件名是一个有限长度的字符串,它一般由两个部分组成: 文件名和扩展名。有的系统要求文件名的长度一般不超过 8 个字符,但是很多系统支持长的文件名。

        文件的逻辑结构指的是文件系统向外提供给用户的文件结构形式,它独立于文件在磁盘上的物理存储结构文件的逻辑结构主要有三种:无结构、简单的记录结构和复杂结构。对于现代文件系统,通常采用的是无结构的形式。也就是说,整个文件是由一个无结构的字节流所组成,文件的大小也就是这些字节的个数。

2、文件的使用

1)文件的存取方法

文件的存取方法可以分为两类:

        (1)顺序存取:对于文件中的每一个字节或记录,只能从起始位置开始,一个接一个地顺序访问,不能跳跃式访问

        (2)随机存取:根据所需访问地字节或记录在文件中的位置,将文件的读写指针直接移至该位置,然后进行存取,每一次存取操作都要指定该操作的起始位置

2)文件的访问

(1)打开操作

(2)关闭操作

(3)读操作

(4)写操作

(5)添加操作

(6)定位操作

3)文件的控制

        文件的控制是指与文件属性控制有关的各种文件操作,包括文件的创建、删除、读取文件属性、设置文件属性、修改文件名等

3、目录

在多级目录结构中,主要有两种方法来指定需要访问的文件或目录

        (1)绝对路径名:对于每一个文件或目录,可以用从根目录开始依次经由的各级目录名,再加上最终的文件名或目录名来表示,在每一级目录名之间,用分隔符隔开。一个文件或目录的绝对路径名是唯一的,例如: spel\mail\copy\all。

        (2)相对路径名:用户首先指定一个目录作为当前的工作目录,然后在访问一个文件或目录时,可以使用相对于当前工作目录的部分路径名,即相对路径名,例如,假设当前的工作目录是\spel\mail\copy,那么使用相对路径名 all 的效果等价于使用绝对路径\spell\mail\copy\all。

4.6.3 文件系统的实现

1、数据块

        文件的逻辑结构一般是字节流,即无结构。用户程序可以在这种字节流的基础上,构造自己所需的各种数据结构。由于文件是存放在磁盘等存储设备当中,而这些设备的访问单元并不是字节。

        例如,在磁盘中,是以扇区为单元来进行读写操作的。因此,对于文件系统而言,必须将用户提交的这种字节流(一个连续的逻辑地址空间)映射为磁盘所需要的扇区。为了实现设备的独立性,通常的做法是把磁盘空间划分为个个大小相同的块,称为物理块,每个物理块包含若干个连续的扇区。同时把文件的字节流也分成大小相同的逻辑块。然后在文件系统的内部,以块为单位来进行操作,把每个逻辑块保存在一个物理块当中。

2、文件的实现

1)文件控制块

        文件控制块 (FCB) 是操作系统为了管理文件而设置的一种数据结构,用于记录与一个文件有关的所有管理信息。FCB 是文件存在的标志。对于不同的操作系统,它们的文件控制块所包含的内容是各不相同的。一般来说主要包含两类信息:

        (1)文件的属性信息:包括文件的类型和长度、文件的所有者、文件的访问权限、文件的创建时间、最后访问时间以及最后修改时间等。

        (2)文件的存储信息:文件在磁盘上的存放位置,它被存放在哪一些物理块当中。

2)文件的物理结构

        文件的物理结构研究的是如何把一个文件存放在磁盘等物理介质上。具体来说,就是以块为单位,研究如何把文件的一个个连续的逻辑块存放在不同的物理块当中,从而建立逻辑块与物理块之间的映射关系。文件的物理结构主要有三种形式:连续结构、链表结构和索引结构。

        (1)连续结构,也叫顺序结构,基本思想是把文件的各个逻辑块按照顺序存放在若干个连续的物理块中。优点是简单、易于实现。

        (2)链表结构,基本思想是把文件的各个逻辑块一次地存放在若干个物理块当中,这些物理块即可以是连续的,也可以是不连续的,然后在各个块之间通过指针连接起来,前一个物理块指向下一个物理块,从而形成一条链表。

        (3)索引结构,基本思想是把文件当中每一个逻辑块所对应的物理块编号直接记录在这个文件的文件控制块当中,这样的文件控制块称为 I 结点,或者索引节点。这样,每一个文件都有一个自己的索引结点,通过这个索引结点,就能直接地实现逻辑块与物理块之间的映射关系。

3、目录的实现

分为两种类型:即        直接法和间接法

        (1)直接法:如图a所示,把文件控制块的内容直接保存在目录项当中,因此,每一个目录项就等于某个文件的文件名加上它的 FCB,包括文件的各种属性信息和它在磁盘上的存放位置

        (2)间接法:如图b所示,每一个文件的FCB不是保存在它的目录项当中,而是单独存放,然后在每一个目录项里面,只有两个内容:文件名和该文件的FCB所在的地址

        注:不管是哪种类型的实现方法,目录的基本功能都是一样的,即如果用户给出一个文件名,就返回相应文件的FCB

4、空闲空间的管理

        为了管理磁盘上的空闲空间,系统会维护一个空闲空间列表,记录了磁盘上所有的空闲物理块,具体实现时,有三种方法:位图法、链表法和索引法

        (1)位图法:每一个物理块用1个位来标识,如果该物理块空闲,相应位的值为1,如果该物理块已分配,那么相应位的值为0

        (2)链表法:在每一个空闲的物理块上都有一个指针,然后把所有的空闲块通过这个指针连接起来,形成一个链表,文件系统只要记住这个链表的首结点指针,就可以去访问所有的空闲的物理块

        (3)索引法:对链表法的一种修改,同样构造一个空闲链表,但是这个链表中的物理块本身并不参与分配,而是专门用来记录系统中其他空闲物理块的编号(索引)

4.7 嵌入式数据库

4.7.1 嵌入式系统对数据库的特殊要求

1、采用纯内存的工作方式

        嵌入式数据库的整个架构应当以内存为出发点,在索引、存储管理、数据结构等方面针对内存环境进行涉及,不应将现有的磁盘数据库技术简单地迁移到内存盘上。

2、为特殊数据类型提供高效索引

        嵌入式数据库通常管理一些较为特殊的数据类型,如坐标、地图数据等。

3、支持基于优先级的多任务访问

        嵌入式数据库的多任务访问应当基于任务优先级进行管理,嵌入式数据库不应采用先进先出等简单的调度策略,而是需要配合操作系统任务优先级,否则数据库的多任务控制会抵消系统对访问数据库任务的优先级设置,影响系统的性能和稳定性。

4、可靠性、持久性和高可用性方面

        (1)可靠性:嵌入式数据库的外部接口应当是类型安全的,不应使用Void指针,消除数据库内部的动态内存分配,如malloc和free操作,从而避免潜在的内存泄露风险。

        (2)持久性:是指数据库能够从软件或硬件错误中恢复数据的能力,持久性对于以内存为主的嵌入式数据库尤为关键

        (3)高可用性方面:嵌入式数据库的高可用性通过对主数据库建立一个或多个冗余的从数据库实现,主数据库与从数据库之间通过一定的方式保持着数据同步,一旦主数据库出现问题,可以立即切换从数据库,继续服务。

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
学习嵌入式系统基础知识的方法有很多种,以下是一些建议: 1. 了解嵌入式系统的概念和基本原理。嵌入式系统是一种专用计算机系统,用于控制和执行特定任务。它通常包括硬件和软件两个方面。了解嵌入式系统的基本概念和原理是学习的第一步。 2. 学习数字电路和电子电路的基础知识嵌入式系统中的硬件部分主要包括各种电子元器件和电路。了解数字电路和电子电路的基础知识,包括电平、逻辑门、时序电路等,对于理解嵌入式系统的工作原理非常重要。 3. 学习微控制器和单片机的原理和应用。微控制器和单片机是嵌入式系统中常用的硬件平台。学习它们的原理和应用,包括寄存器、中断、定时器等,可以帮助你理解嵌入式系统的编程和控制。 4. 学习嵌入式系统的编程语言和开发工具。嵌入式系统软件部分通常使用特定的编程语言和开发工具进行开发。常见的嵌入式系统编程语言包括C、C++和汇编语言。学习这些编程语言,并掌握相应的开发工具,可以帮助你进行嵌入式系统软件开发。 5. 进行实际的项目实践和实验。学习嵌入式系统最好的方法是通过实际的项目实践和实验。选择一个简单的嵌入式系统项目,例如LED灯控制、温度传感器等,进行实际的搭建和编程实验,可以帮助你更好地理解和掌握嵌入式系统基础知识

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值