1.1 操作系统概述
1. 1.1 什么是操作系统
操作系统OS(Operating System)是裸机上的第一层软件。操作系统是计算机系统中最重要的系统软件,是硬件的第一层封装与抽象,在计算机系统中占据着重要的地位,所有其他的系统软件与应用软件都依赖于操作系统的支持与服务。除提供编程接口,操作系统还承担着任务管理、事件管理和消息通信、CPU管理、内存管理、IO管理等核心功能
1.1. 2 操作系统基本功能
1.任务管理
任务是程序的一次执行。任务可以分为系统任务和用户任务。系统任务是操作系统本身的任务,如操作系统的主程序,时钟中断服务程序,如后面要讲到的空闲任务和统计任务等。用户任务是用户应用程序的运行,如用户设计的计算器软件的一次执行或WORD软件的运行,如本书中给出的一些用户任务。这些任务都需要任务管理部分来管理。
2.CPU管理
CPU管理的含义在于多任务OS对CPU的分配,也就是分配对CPU的所有权,简单说,哪个软件正在运行,占有CPU。可以把它归入任务管理。
3.内存管理
内存是任务的生存空间。内存管理用于给任务分配内存空间,相应的,在任务结束后释放内存空间。
4.文件管理
文件管理系统是实现对文件的统一管理,是对文件存储器的存储空间进行组织,分配和回收,负责文件的存储,检索,共享和保护。从用户角度来看,文件系统主要是实现"按名取存",文件系统的用户只要知道所需文件的文件名,就可存取文件中的信息,而无需知道这些文件究竟存放在什么地方。
5.IO设备管理
管理系统中的各种硬件设备,如打印机,显示器,硬盘等。很明显,用户应用程序应该调用IO设备管理模块提供的API来对设备进行操作,而不是直接读写硬件。
1.2实时操作系统概述
1.2.1什么是实时操作系统
�实时操作系统RTOS(Real Time Operating System)是指当外界事件或数据产生时,能够接收并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的操作系统
实时系统与非实时系统的本质区别就在于实时系统中的任务都有时间限制。
1.2.1实时操作系统基本特征
1.实时操作系统首先是多任务操作系统。
2.多级中断机制。
3.优先级调度机制。
1.3任务
1.1.3.1任务
�任务是程序的动态表现,在操作系统中体现为线程,是程序的一次执行过程。
程序是静止的,存在于ROM、硬盘等外部设备。任务是运动的,存在于内存中,有睡眠、就绪、运行、阻塞、挂起等多种状态。
相同的程序的多次执行是可以的,就形成了多个优先级不同的任务,每一个都是独立的。
在实时系统中,把应用程序的设计过程分割为多个任务,每个任务都有自己的优先级,在操作系统的调度下协调运行。
1.3.2多任务
实时操作系统的是多任务的操作系统,系统中必然有多任务在执行。其中有用户任务,如前面的usertask,也有操作系统的系统任务如空闲任务和统计任务。多任务的运行相对于其他的系统,其优点是可以大大提高CPU的利用率,又必然使应用程序分成多个程序模块,实现模块化,应用程序更易于设计和维护。
在嵌入式应用的场合的多任务使用的例子是在一个ARM采集处理系统中,同时采集16路信号,同时又要对多信号进行处理和传输,可以创建16个任务负责16路信号的采集,创建一个任务对信号进行处理,再创建一个任务负责数据的传输。
1.3.3任务状态
1.睡眠态
任务已经被装入内存了,可是并没有准备好运行。例如上面给出的usertask代码,以代码的形式存在于内存中,在调用OSTaskCreate(任务创建函数)创建之前,处于睡眠态。睡眠态的任务不会得到运行的,操作系统也不会给其设置为运行而准备的数据结构。
2.就绪态
当操作系统调用OSTaskCreate创建一任务后,任务就进入就绪态。从图1.4还可以看出,任务也可以从其他状态转到就绪态。处于就绪态的任务操作系统已经为其运行配置好了任务控制块等数据结构,当没有比其更高优先级的任务,或比其优先级更高的任务处于阻塞状态的时候,就能被操作系统调度而进入运行态。从就绪态到运行态,操作系统调用任务切换函数完成。
3.运行态
任务真正占有CPU,得到运行。这时运行的代码就是任务的代码。如usertask。处于运行态的任务如果运行完成,就会转为睡眠态。如果有更高优先级的任务抢占了CPU,就会转到就绪态。如果因为等待某一事件,例如等待一秒钟的时间,如OSTimeDly(OS_TICKS_PER_SEC),需要暂时放弃CPU的使用权而让其他任务得以运行,就进入了阻塞状态。当由于中断的到来而使CPU进入中断服务程序(ISR),必然使正在运行的任务放弃CPU而转入中断服务程序,这时被中断的程序就被挂起而进入挂起态。
总之,任务要得到运行必须进入运行态,CPU只有一个不能让每个任务同时进入运行态,进入运行态的任务有且只有一个。
4.阻塞态
阻塞对于操作系统的调度,任务的协调运行是非常重要的。我们能看到图1.3的运行结果,而不是只有一个高优先级的任务得到运行,就是因为usertask在没有事情可做,等待一秒钟的时候,不是强行运行代码,而是把自己阻塞起来,使操作系统可以调度其他的任务。
当任务在等待某些还没有被释放的资源,等待一定的时间等时候,要阻塞起来,等到条件满足的时候再重新回到就绪态,又能被操作系统调度以进入运行态,这是实时系统必须要实现的功能之一。
一些不理解操作系统的同学在编程的时候,在等待的时候常常使用FOR循环,不停的执行代码而使CPU的利用率暴增,使系统的运行环境十分恶劣,甚至造成死机,是不可取的
5.挂起态
当任务在运行时,因为中断的发生,例如定时器中断每个时钟滴答(clock
tick,指每个时钟周期)中断一次,而被剥夺CPU的使用权,而进入挂起态。在中断返回的时候,若该任务还是最高优先级的,就恢复运行,如果不是这样,只能回到就绪态。
1.3.4任务切换
任务切换就是context switch,是任务调度的重要部分。从字面上是上下文切换。任务切换是暂停一个任务的运行,运行另一个就绪的任务。暂停一个任务,以后又能恢复运行,必须考虑将这个任务运行的信息保存,而恢复运行的时候需要将这些信息恢复到运行环境。
任务切换必须做环境的保存和恢复的操作。
在操作系统移植的时候,任务切换代码就是必须要实现的部分之一。
1.3.5可重入和不可重入函数
函数可重入是指一个函数可以被多个任务调用,而不需要担心在任务切换的过程中,代码的执行会产生错误的结果。
如果函数被多个任务调用,可能产生错误的结果,就是不可重入函数。
1.4 内核
1.4.1内核
�内核是操作系统最核心的部分,其主要功能就是进行任务调度。所谓调度,就是决定多任务的运行状态,哪个任务应该处于图1.4中的哪种状态。内核中最最核心的基本服务就是调度的核心——任务切换
μC/OS使用的是一种基于优先级的可剥夺型内核。
1.4.1基于优先级的调度算法
在μC/OS中,可以同时有64个就绪任务,每个任务都有各自的优先级。优先级用无符号整数来表示,从0到63,数字越大则优先级越低。
μC/OS总是调度就绪了的,优先级最高的任务获得CPU的控制权,不管这个任务是什么,执行什么样的功能,也不管该任务是否已经等了很久。
1.5 同步和通信
�1.5.1同步
�任务是独立的,但是任务之间又有着各种各样的关系,以成为一个整体,来完成某一项工作。有时候一个任务完成的前提是需要另一个任务给出一个结果,任务之间的这种制约性的合作运行机制叫做任务间的同步。
例如,A任务实现计算功能,B任务输出A任务计算的结果,然后循环运行。A任务和B任务就必须同步,否则B任务输出的可能不是A任务刚完成的结果,或则B任务访问结果时,A任务正在修改,因而输出错误的结果。A和B就是必须进行同步的任务。
�1.5.2互斥
前面的例子中,A和B两个任务都要访问计算结果这个共享资源,但是在A写这个资源的同时,B必须等待,而不能在A写到一半的时候结束A而让B来读,这样会产生灾难性的后果。
这样的共享资源称为临界资源(Critical Resource)。
这种访问共享资源的排他性就是互斥。
1.5.3临界区
每个任务中访问共享资源的那段程序称为临界区(Critical Section),因为共享资源的访问是要互斥的。在临界区不允许任务切换,
这是最根本的原则。因为如果在访问共享资源的时候进行任务切换,就可能发生前面提到的灾难性后果。因此,在进入临界区访问共享资源之前,采用关中断,给调度器上锁或使用信号量的方法,达到互斥的目的。
访问临界区的例子
1.5.4任务事件
事件(Event)就是在操作系统运行过程中发生的事情。例如任务被挂起、唤醒、创建等。
μC/OS操作系统在处理任务的同步和通信等环节,大量的使用了事件这一概念,创建了事件控制块这样的数据结构以进行事件的管理。
1.5.5信号量
在一个时刻,有些共享资源只可以被一个任务所占有,而有些可以被至多N个任务所共享。前一种共享资源就好比有一把钥匙,钥匙发出去了,得到钥匙的任务可以访问共享资源,其他请求该资源的任务必须等得到钥匙的任务把钥匙归还。后者则可以有N把钥匙,如果N把钥匙都发完了,第N+1个请求访问共享资源的任务就必须等待。这些钥匙就可以用信号量(semaphore)来表示。
信号量标志了共享资源的有效可被访问数量,于是要获得共享资源的访问权,就首先要得到信号量这把钥匙。
1.5.6互斥信号量
互斥信号量是一种特殊的信号量,这不仅在于该信号量只有用于互斥资源的访问,还在于使用互斥信号量管理需要解决的优先级反转问题。
如系统中有三个任务分别是高优先级、中优先级和低优先级的,当低优先级的任务在运行的时候访问互斥资源,而中优先级的任务运行的时候将使低优先级的任务得不到运行而死抱着资源不放。这是高优先级的任务开始运行的时候,必须等待中优先级的任务运行完成,然后等低优先级的任务访问资源完成才行。如果在低优先级的任务访问资源过程中又有中优先级任务运行,那么高优先级的任务只有继续等待。这种情况就是优先级反转。
1.5.7事件标志组
在信号量和互斥信号量的管理中,任务请求资源,如果资源未被占用就可继续运行,否则只能阻塞,等待资源释放的事件发生。这种事件是单一的事件。如果任务要等待多个事件的发生,或多个事件中的某一个事件的发生就可以继续运行,那么就应该采用事件标志组管理。
事件标志组管理的条件组合可以是多个事件都发生,也可以是多个事件中有任何一个事件发生。尤其特别的是,还可以是多个事件都没有发生或多个事件中有任何一个事件没有发生。
1.5.8 消息邮箱和消息队列
邮箱(MailBox)很明显是用于通信的,邮箱中的内容一般是信件。操作系统也通过邮箱来管理任务间的通信与同步,邮箱中的内容却不是信件本身,而是指向消息内容的地址!这个指针是void类型的,可以指向任何的数据结构。因而这样的设计更经济,所发送的信息范围也就更宽,邮箱中可以容纳下任何长度的数据了。
消息队列(message queue)也用于给任务发消息,但是它是由多个消息邮箱组合形成的,是消息邮箱的集合,实质上是消息邮箱的队列。一个消息邮箱只能容纳一条消息,采用消息队列,一是可以容纳多条消息,二是消息是有序的。
1.6中断和时钟
嵌入式实时操作系统的中断是指在任务的执行过程中,当出现异常情况或特殊请求时,停止任务的执行,转而对这些异常情况或特殊请求进行处理,处理结束后再返回当前任务的间断处,或由于中断服务程序使更高优先级的程序就绪,转而执行优先级更高的任务。中断是实时地处理内部或外部事件的一种内部机制。这里异常情况或特殊请求是中断源,称为异步事件,处理异步事件所的程序是中断服务程序。
1.7内存管理
μC/OS-II中,采用分区的方式管理内存,即将连续的大块内存按分区来管理,每个系统中有数个这样的分区,每个分区又包含数个内存块,每个内存块大小相同。这样,在分配内存的时候,根据需要从不同的分区中得到数个内存块,而在释放时,这些内存块重新释放回他们原来所在的分区。 这样就不会产生内存越分越凌乱,没有整块的连续分区的问题了。
网友评论