在RTOS中,线程与调度是两个最重要概念,本节首先阐述这两个概念,然后给出RTOS的其他相关术语,简单地分为内核类与线程类的相关术语,理解这些基本概念是学习RTOS的关键一环。这里的内核是指RTOS的核心部分,是RTOS厂家提供的程序,而线程则是指应用程序设计者编制的程序,它在内核的调度下运行。
线程与调度是RTOS中两个不可分割的重要的基本概念,透彻地理解它们,对RTOS的学习至关重要。
1.线程的基本含义
线程是RTOS中最重要的概念之一。在RTOS下,把一个复杂的嵌入式应用工程按一定规则分解成一个个功能清晰的小工程,然后设定各个小工程的运行规则,交给RTOS管理,这就是基于RTOS编程的基本思想。这一个个小工程被称为线程(Thread),RTOS管理这些线程,被称为调度(Scheduling)。
要给RTOS中的线程下一个准确而完整的定义并不十分容易,可以从不同视角理解线程。从线程调度视角理解,可以认为,RTOS中的线程是一个功能清晰的小程序,是RTOS调度的基本单元;从RTOS的软件设计视角来理解,就是在软件设计时,需要根据具体应用,划分出独立的、相互作用的程序集合,这样的程序集合就被称为线程,每个线程都被赋予一定的优先级;从CPU视角理解,在单CPU下,某一时刻CPU只会处理(执行)一个线程,或者说只有一个线程占用CPU。RTOS内核的关键功能就是以合理的方式为系统中的每个线程分配时间(即调度),使之得以运行。
实际上,根据特定的RTOS,线程可能被称为任务(Task),也可能使用其他名词,含义或许稍有差异,但本质不变,也不必花过多精力追究其jingque语义,因为学习RTOS的关键在于掌握线程设计方法、理解调度过程、提高编程鲁棒性、理解底层驱动原理、提高程序规范性、可移植性与可复用性、提高嵌入式系统的实际开发能力等。要真正理解与掌握利用线程进行基于RTOS的嵌入式软件开发,需要从线程的状态、结构、优先级、调度、同步等视角来认识,将在后续章节中详细阐述。
2.调度的基本含义
多线程系统中,RTOS内核(Kernel)负责管理线程,或者说为每个线程分配CPU时间,并且负责线程间的通信。
调度(Scheduling)就是决定该轮到哪个线程运行了,它是内核最重要的职责。每个线程根据其重要程度不同,被赋予一定的优先级。不同的调度算法对RTOS的性能有较大影响,基于优先级的调度算法是RTOS常用的调度算法,其核心思想是,总是让处于就绪态的、优先级最高的线程先运行。然而何时高优先级线程掌握CPU的使用权,由使用的内核类型确定,基于优先级的内核有不可抢占型和可抢占型两种类型。
在RTOS场景下编程,芯片启动过程先运行一段被称为RTOS内核的程序代码,这段代码的功能是:开辟好用户线程的运行环境,准备好对线程进行调度。RTOS一般由内核与扩展部分组成,内核的最主要功能是线程调度,扩展部分的最主要功能是提供应用程序编程接口(API)。内核类其他基本概念主要有:时间嘀嗒、代码临界段、不可抢占型内核与可抢占型内核、实时性相关概念及RTOS实时性指标等。
1.时间嘀嗒
时钟节拍(Clock Tick),有时也直接译为时钟嘀嗒,它是特定的周期性中断,通过定时器产生周期性的中断,以便内核判断是否有更高优先级的线程已进入就绪状态。
2.代码临界段
代码临界段也称为临界区,是指处理时不可分割的代码,一旦这部分代码开始执行,则不允许任何中断打扰。为确保临界段代码的执行,在进入临界段之前要关中断,且临界段代码执行完后应立即开中断。
3.不可抢占型内核与可抢占型内核
不可抢占型内核(Non-Preemptive Kernel),要求每个线程主动放弃CPU的使用权,不可抢占型调度算法也称为合作型多线程,各个线程彼此合作共享一个CPU。但异步事件还是由中断服务来处理,中断服务可使高优先级的线程由挂起态变为就绪态,但中断服务以后,使用权还是回到原来被中断了的那个线程,直到该线程主动放弃CPU的使用权,新的高优先级的线程才能获得CPU的使用权。
当系统响应时间很重要时,须使用可抢占型内核(Preemptive Kernel)。在可抢占型内核中,一个正在运行的线程可以被打断,而让另一个优先级更高且变为就绪态的线程运行。如果是中断服务子程序使高优先级的线程进入就绪态,中断完成时,被中断的线程被挂起,优先级高的线程开始运行。
4.实时性相关概念及RTOS实时性指标
硬实时(Hard Real-Time)要求在规定的时间内必须完成操作,是在设计操作系统时保证的,通常将具有优先级驱动的、时间确定性的、可抢占调度的RTOS系统称为硬实时系统。软实时(Soft Real-Time)则没有那么严格,只要按照线程的优先级,尽可能快地完成操作即可。
RTOS追求的是调度的实时性、响应时间的可确定性、系统的高度可靠性,评价一个RTOS一般可以从线程调度、内存开销、系统响应时间、中断延迟等几个方面来衡量。
(1)线程调度的时间指标
RTOS的实时性和多线程能力在很大程度上取决于它的线程调度机制。在大多数商用的实时系统中,为了让操作系统能够在有突发事件时迅速取得系统使用权,以便对事件做出反应,所以大都提供了“抢占式线程调度”功能,也就是操作系统有权主动终止应用程序(应用线程)的执行,并且将执行权交给拥有最高优先级的线程。
调度延时(Scheduling Latency):指当一个更高优先级的线程就绪到这个线程开始运行之间的时间。简而言之,就是一个线程被触发后,由就绪到开始运行的时间。
线程切换时间(Context-Switching Time):由于某种原因使一个线程退出运行时,RTOS保存它的运行现场信息,并插入相应列表,依据一定的调度算法重新选择一个新线程使之投入运行,这一过程所需时间称为线程切换时间。线程切换时间越短,RTOS的性能就越高。
恢复时间(Recovery Time):指从线程完成后,系统响应到恢复执行主程序所需要的时间。
(2)最小内存开销
在RTOS的设计过程中,由于成本限制,嵌入式系统产品内存的配置一般都不大,而在有限的内存空间内不仅要装载RTOS,还要装载用户程序。因此,最小内存开销是一个重要的指标,这是RTOS设计与其他操作系统设计的明显区别之一。
(3)系统响应时间
系统响应时间(System response time):指系统发出处理要求到系统给出应答信号的时间,也就是从线程请求产生到线程完成之间的时间间隔,需要满足一定的时间约束。控制要满足一定的实时性要求,就是响应时间小于临界时间。系统响应时间由反应时间和处理时间两部分组成,反应时间指外部中断提交到CPU开始处理的时间,处理时间指CPU完成处理的时间。提高系统的响应时间,可以从缩短反应时间和处理时间两个方面入手。反应时间是电信号的传导时间,对于不同速度的处理器,这个时间相差不大。
(4)中断延迟
中断是一种硬件机制,用于通知CPU发生了一个异步事件。CPU一旦识别出一个中断,保存线程上下文后,跳至该中断服务程序(ISR)执行,处理完这个中断后,返回到就绪列表中具有最高优先级的线程执行。当RTOS运行在核心态或执行某些系统调用的时候,不会因为外部中断的到来而立即执行中断服务程序,只有当RTOS重新回到用户态时才响应外部中断请求,这一过程所需的最大时间就是中断禁止时间。
中断延迟(Interrupt latency)时间:是指系统确认中断开始直到执行中断服务程序第一条指令为止,整个处理过程所需要的时间。中断禁止时间越短,则中断延迟时间越短,那么系统的实时性也会越高。
这里归纳线程类其他基本概念主要有:线程的上下文及线程切换、线程间通信、死锁、线程优先级、优先级驱动、优先级反转、优先级继承、资源、共享资源与互斥等。
1.线程的上下文及线程切换
线程的上下文(Context),即CPU内寄存器。当多线程内核决定运行另外的线程时,它保存正在运行线程的当前上下文,这些内容保存在随机存储器(Random Access Memory,RAM)中的线程当前状况保存区(Task’s Context Storage Area),也就是线程自己的堆栈之中。入栈工作完成以后,就把下一个将要运行线程的当前状况从其线程堆栈中重新装入CPU的寄存器,开始下一个线程的运行,这一过程叫作线程切换或上下文切换。
2.线程间通信
线程间通信是指线程间的信息交换,其作用是实现同步及数据传输。同步是指根据线程间的合作关系,协调不同线程间的执行顺序。线程间通信的方式主要有事件、消息队列、信号量、互斥量等。有关线程间通信及下述的优先级反转、优先级继承、资源、共享资源与互斥等概念将在后续章节中详细阐述。
3.死锁
死锁指两个或两个以上的线程无限期地互相等待对方释放其所占资源。死锁产生的必要条件有4个,即资源的互斥访问、资源的不可抢占、资源的请求保持以及线程的循环等待。解决死锁问题的方法是破坏产生死锁的任一必要条件,例如规定所有资源仅在线程运行时才分配,其他任意状态都不可分配,破坏其资源请求保持特性。
4.线程优先级、优先级驱动、优先级反转、优先级继承
在一个多线程系统中,每个线程都有一个优先级(Priority)。
优先级驱动(Priority-Driven):在一个多线程系统中,正在运行的线程总是优先级最高的线程。在任何给定的时间内,总是把CPU分配给优先级最高的线程。
优先级反转(Priority- Inversion):当一个线程等待比它优先级低的线程释放资源而被阻塞时,这种现象被称为优先级反转,这是一个需要在编程时必须注意的问题。优先级继承技术可以解决优先级反转问题,目前市场上大多数商用操作系统都使用优先级继承技术。
优先级继承(Priority-Inheritance):优先级继承是用来解决优先级反转问题的技术。当优先级反转发生时,较低优先级线程的优先级暂时提高,以匹配较高优先级线程的优先级。这样,就可以使较低优先级线程尽快地执行并且释放较高优先级线程所需要的资源。
5.资源、共享资源与互斥
资源(Resources):任何为线程所占用的实体均可称为资源。资源可以是输入/输出设备,例如打印机、键盘及显示器,也可以是一个变量、结构或数组等。
共享资源(Shared Resources):可以被一个以上线程使用的资源叫作共享资源。为了防止数据被破坏,每个线程在与共享资源打交道时,必须独占资源,即互斥。
互斥(Mutual Exclusion):互斥是用于控制多线程对共享数据进行顺序访问的同步机制。在多线程应用中,当两个或更多的线程同时访问同一数据区时,就会造成访问冲突,互斥能使它们依次访问共享数据而不引起冲突。