1.1.应用软件开发指导 VxWorks系统是专为嵌入式实时应用而设计的模块化的实时操作系统。对于用户来说,一个实时应用软件是由板级支持包BSP、操作系统内核及用户选用组件、中断服务程序ISR组成。操作系统为用户提供了大量的系统调用,这是用户与操作系统的接口。针对当前开发工作和实时系统的特性,在实时应用软件的编制中要注重以下问题:
2.5.1 任务划分要合理
1.功能内聚性
对于功能联系比较紧密的各工作可以作为一个任务来运行。如果都以一个个任务来进行相互之间的消息通信,影响系统效率,不如采用任务中一个个独立的模块来完成。
2.时间紧迫性
对于实时性要求比较高的任务,要以高优先级运行,以保证事件的实时响应。
3.周期执行原则
对于一个需周期性执行的工作,应作为一个任务来运行,通过定时器以一定时间间隔激活任务。
2.5.2 防止死锁、饥饿和优先级翻转
死锁是指多个任务因为等待进入对方占据的临界区而导致的不可自行恢复的运行终止。在程序设计是要注意对死锁的预防,一个是尽量使互斥资源在相同优先级任务中使用,必须在不同优先级任务中使用时,要注意对死锁的解锁处理。
饥饿是指优先级较低的任务长期得不到系统资源(主要是指CPU资源)而造成的任务长期得无法运行。造成饥饿的主要原因是优先级较高的任务调度过于频繁或占用时间太长。合理的分配任务的优先级和对较高优先级任务的合理调度是解决饥饿的不二法门。
任务的优先级翻转是实时多任务操作系统的热门话题,它是指高优先级任务因等待低优先级任务占用的互斥资源而被较低优先级(高于低优先级但低于高优先级)的任务不断抢占的情况。有些实时多任务操作系统自身提供保护机制可对优先级翻转进行预防。在操作系统未提供保护的情况下,就需要编程人员在编程的时候注意避免优先级翻转的情况发生(如在同一优先级内使用互斥资源),或采取相应的手段进行处理(如动态的进行优先级提升)。
注:VRTX和VxWorks提供自身的防止优先级翻转机制,pSOS未提供保护机制。
2.5.3 函数的可重入性(Reentrancy)正确运用
在一个多任务环境中,函数的可重入性是十分重要的。可重入函数是一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。在写函数时只要考虑到尽量用局部变量(例如寄存器、堆栈中的变量),对于要使用的全局变量要加以保护(例如采用关中断、信号量等),这样构成的函数就一定是一个可重入的函数。
此外,编译器是否有可重入函数的库,与它所服务的操作系统有关,例如DOS下的Borland C和Microsoft C/C++等就不具备可重入的函数库,这是因为DOS是一个单用户单任务的操作系统。为了确保每一个任务控制自己的私有变量,在一个可重入的C函数中,须将这样的变量声名为局部变量。C编译器将这样的变量存放在调用栈上或寄存器里。
在VxWorks中,多个任务可调用同一子函数或函数库。VxWorks系统动态连接工具使这相当容易,这种共享代码让系统更加高效,易于维护。
VxWorks系统主要采用如下的几种可重入技术:
Ÿ 动态堆栈变量
许多子函数只是纯代码,除了动态堆栈变量外没有其他数据。调用程序的参数作为子函数的数据。这种子函数是完全可重入的,多个任务同时使用这种子函数,不会互相影响,因为它们各有自己的堆栈空间。
Ÿ 受保护的全局和静态变量
一些函数库包含公有数据,多个任务的同时调用很可能会导致对公有数据的破坏,使用起来要格外小心。系统采用信号量互斥机制来防止任务同时运行代码的临界区。
Ÿ 任务变量
一些公用函数要求对于每一调用程序都有明确的全局或静态变量值。为了满足这一点,VxWorks提供的任务变量允许4字节变量加入到任务上下文中,当任务切换时变量的值也切换。
编写可重入的函数,必须遵循以下的规则:
1.将所有的局部变量申明为auto(缺省态)或寄存器型。
2.尽量不要使用static或extern变量。如有必要,要用互斥机制进行保护。
2.5.4 使用名称访问资源
通过任务名、消息队列名、信号量名来调用这些资源,能保证应用系统运行的可靠性,同时也便于程序的阅读。例如系统调用taskName(),taskNameToId(),taskIsSelf()等,都方便了用户对资源的管理,更加直观化。
2.5.5 用户任务优先级确定
VxWorks系统中优先级分为256级,从0到255,其中0为最高优先级,255为最低优先级.任务的优先级在任务创建时被分配,但在任务运行时可通过系统调用taskPrioritySet()动态改变其优先级。当操作系统在目标板上启动成功后,系统级任务已在运行,对主机与目标机之间的通信进行管理,因此用户任务优先级要低于系统级任务,一般最高为150。同时,对于用户各任务优先级的确定,如何让各任务间良好的协同工作,有待于用户根据任务的紧急程度以及实际情况进行给定,调测过程中的摸索总结也很重要。