
图3 进程调用执行过程的SDL描述
4 二级调度的实现
每个调度任务创建一个VxWorks定长消息队列,任务被创建后就无限循环运行,不断从自己要处理的消息队列中取消息,如果任务下所有进程的消息队列都为空,任务在其所操作的VxWorks消息队列上等待消息,此时,VxWorks令该任务阻塞,直到在其所等待的消息队列上有一个消息到来时,VxWorks才唤醒该任务,这种策略使其它被低优先级调度任务所调度的进程获得运行机会[2]。
当一个调度任务被VxWorks调度运行后,该任务将从其所操作的VxWorks消息队列上获得消息,并把取到的消息指派给相应的进程,同时把阻塞且获得消息的进程放到任务的进程就绪队列尾部,然后开始循环调度进程的执行[3]。调度任务每次调度进程就绪队列中的第一个进程,当将被调度的进程是由于同步消息已经应答或延时已经到时而被唤醒时,调度任务将控制转移到保存在进程堆栈中的指令地址;否则,如果进程消息队列头上的是一条新消息,调度任务依据进程消息队列头上的消息和PCB中的数据为进程的主处理函数传递相应入口参数,并从主处理函数的第一条语句开始执行。
进程依据入口参数获得当前消息,完成对应用层的通用外部接口调用和VxWorks的接口函数调用后,调用“退出进程”外部接口函数通知调度进程已经完成了一次消息处理,并将控制返回给调用任务。控制权返回给调度任务后,调度任务将刚刚处理过的进程从进程就绪队列头摘下,并将刚处理过的消息从该进程的消息队列头摘下,如果此时的进程消息队列为空,当前任务将进程置到任务的进程阻塞队列尾部,否则将进程置到进程就绪队列尾部,任务每调度进程执行一次,所有进程就绪队列中进程的相对位置就要发生一次变化,即循环向前移动了一下,这种调度机制保证了同一任务下的所有就绪进程获得平等的运行机会。
5 调度流程

图4 调度进程示意图
在图4中,在派发消息链表中的消息时:
(1)如果接收消息的进程处在阻塞状态,且此时不是在等待同步应答,消息将成为进程PCB消息队列的当前消息,该进程PCB将从阻塞队列进入就绪队列尾;若此时在等待同步应答,则仅将该消息添加到进程PCB消息队列尾。
(2)如果接收消息的进程已经在就绪状态,则将该消息添加到进程PCB消息队列尾。
(3)如果待分发的消息是同步定时器超时消息或同步应答消息,那么此消息不进入进程PCB的消息队列,直接把该PCB从阻塞队列中挂到就绪队列头。
6 结论
采用二级调度机制可以避免任务间过于频繁的切换,提高速度的同时更有利于系统容量的扩展。在VxWorks操作系统环境下测试的结果显示:进程调度模块效率大约是任务切换的4倍。同时,由于进程调度方式中很大部分(如内存管理、保护、异常处理等)由自己编写和管理,因此在系统初始调试阶段对于错误定位等可以更加方便、快捷。
参考文献
1.VxWorks Programmer’s Guide,[EB/OL]Wind River Systems Inc.,1999
2.Andrew S.Tanenbaum . Modern Operating Systems[M] 北京:机械工业出版社 1999
3.孔祥营,柏桂枝.嵌入式实时操作系统VxWorks及其开发环境Tornado[M].北京:中国电力出版社 2002