最近在做嵌入式开发相关的事情,接触到一种新的操作系统,叫VxWorks。VxWorks不仅是一种嵌入式实时操作系统,又是可以运行的最小基本程序。其内部有BSP(Board Support Package,板级支持包),便于进行驱动程序的编写。此外,VxWorks具有强实时性、微内核设计、可裁剪性、可移植性和可靠性等特点,能较好地满足嵌入式开发的需求。
实时多任务
非实时应用系统可以利用单进程或多进程结构按照事件发生的顺序一次处理,而实时系统则要求按照发生事件的轻重缓急(优先级)来安排处理顺序。对于某些任务,强实时系统甚至要求在给定时间内处理完成。这一点从根本上决定了实时多任务机制的基本功能。
任务的状态
任务被创建后,其状态可以在有限的范围内迁移,从而构成一个简单的有限状态机。任何任务在某一时刻只能处于一种状态,基本状态包括:挂起状态(Suspend)、准备状态(Ready)、阻塞状态(Pend)、延迟状态(Delay)和运行状态(Running)。各种状态的含义及转移状态图与非实时系统类似,此处不做赘述。
任务的调度方式
任务调度最主要的因素是任务的优先级(Priority)。VxWorks支持256个优先级(0~255),数字越小优先级越高。任务调度的另一个因素是调度算法。VxWorks支持两种调度算法,第一种是基于优先级的抢占式调度算法,另一种是同一优先级任务之间所采用的时间片轮转算法,系统默认为第一种算法。
- 基于优先级的抢占式调度算法。
- 算法的基本思想:顾名思义,一个具有更高优先级的任务一旦进入ready状态,将抢占当前运行任务的CPU资源,进行上下文切换后进入运行状态。
- 算法的优点很明显,且符合大多数实时系统的调度需求,因此是最常见的一种选择。
- 缺点是:在多个任务具有相同优先级的情况下,如果当前执行的任务一直不被阻塞,它将一直占有CPU,从而造成其他同优先级或者低优先级任务无法执行。
- 时间片轮转调度算法
- 基本思想:对于处于同一优先级且处于Ready状态的任务来说,算法能使它们分时共享CPU。将任务分为多组,每一组任务具有相同的优先级。从组内的第一个任务开始,每个任务在执行一个时间片后让出CPU,下一个任务开始执行直到组内任务都执行过之后,同组第一个任务重新得到CPU,依次循环。
任务编程
任务的创建
任务创建主要采用taskSpawn
函数(还可以用taskInit
函数和taskActivate
函数,这两者使用时需要同时使用,所以一般使用taskSpawn
)。
1 |
|
option
参数的选择范围如下:
- VX_FP_TASK (0x0008):运行时使用浮点运算器,将浮点寄存器作为任务上下文的一部分
- VX_PRIVATE_ENV (0x0180):允许使用任务的环境变量
- VX_NO_STAKC_FILL (0x0100):人物创建时不以0xEE去填充堆栈,不能使用
checkStack()
- VX_UNBREAKABLE (0x0002):不允许使用断点调试功能
调用成功,返回任务ID;否则返回ERROR并利用errno告知错误原因:
- S_intLib_NOT_ISR_CALLABLE:程序不能从一个中断服务程序中调用
- S_objLib_OBJ_ID_ERROR:不正确的Task ID
- S_memLib_NOT_ENOUGH_MEMORY:没有足够的内存
- S_memLib_BLOCK_ERROR:不能对内存分区互斥访问
1 |
|
系统任务
- 根任务:
tUsrRoot
。内核执行的第一个任务,该任务完成初始化功能并负责创建其他必要的系统任务。 - 日志任务:
tLogTask
。用来输出系统日志信息的任务。在其他任务中,可以调用LogMsg()
向tLogTask
发送消息日至。与printf
相比,好处是无需发起I/O操作,并节省格式化信息所需的大量堆栈空间。中断服务程序可以用LogMsg
,不能使用printf
。 - 异常处理任务:
tExcTask
。用来完成中断不能执行的功能。 - 网络任务:
tNetTask
。用于提供网络所需要使用的任务级功能。 - 目标代理任务:
tWdbTask
。当目标代理设置为运行在任务模式下时,创建这个任务,处理来自Tornado
的目标服务请求。
Shell命令观察和控制
- tt:显示任务的函数栈的调用状态
- ts:挂起某个任务
- tr:恢复某个任务
- td:删除某个任务