VxWorks实时内核Wind提供了基本的多任务环境。对用户而言,宏观上看起来,多个任务同时在执行。而本质而言,在微观上,系统内核中的任务调度器总是在根据特定的调度策略让它们交替运行。系统调度器需要使用任务控制块(TCB)数据结构来管理任务调度功能,TCB被用来描述一个任务。TCB中存放了任务的上下文(context)信息,主要包括程序计数器PC、CPU内部寄存器、浮点寄存器、堆栈指针SP、任务信息等。每一任务都与一个TCB关联,当执行中的任务被停止时,任务的上下文信息需要被写入TCB;而当任务被重新执行时,必须要恢复这些上下文信息。
VxWorks的一个任务可能处于如下几种状态:
Ready:就绪状态(不是运行状态),其他资源已经就绪,仅等待CPU,当获得CPU后,就进入Running状态;
Pended:阻塞状态,由于等待某些资源(CPU除外)而阻塞;
Suspended:挂起状态,这种状态需要用taskResume才能恢复,主要用于调试。不会约束状态的转换,仅仅约束任务的执行;
Delayed:睡眠状态,任务以taskDelay主动要求等待一段时间再执行;
这些状态之间的转换关系如下:
任务状态转换 | 完成方式 |
Ready->pended | 通过semTake()/msgQReceive()调用 |
Ready->delayed | 通过taskDelay() |
ready->suspended | 通过taskSuspend() |
pended->ready | 通过其它任务对semaGive()/msgQSend()的调用 |
pended->suspended | 通过其它任务对taskSuspend()调用 |
delayed->ready | 延迟期满 |
delayed->suspended | 通过taskSuspend()调用 |
suspended->ready | 通过taskResume()/taskActivate()调用 |
suspended->pended | 通过其它任务的taskResume()调用 |
suspended->delayed | 通过其它任务的taskResume()调用 |
VxWorks程序员创建任务需使用如下API:
1
2
3
4
|
taskSpawn (char *name, int priority, int options, int stackSize,
FUNCPTR entryPt, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7,
int arg8, int arg9, int arg10);
|
该API的参数定义如下:
name:任务名;
priority:任务优先级;
options:任务选项,下表给出了各种option及其含义:
选项 | 16进制值 | 含义 |
VX_FP_TASK | 0x0008 | 执行浮点协处理 |
VX_NO_STACK_FILL | 0x0100 | 不对任务堆栈填充0xee |
VX_PRIVATE_ENV | 0x0080 | 执行一个环境私有的任务 |
VX_UNBREAKABLE | 0x0002 | 使任务不能断点 |
VX_DSP_TASK | 0x0200 | 1 = DSP协处理支持 |
VX_ALTIVEC_TASK | 0x0400 | 1 = ALTIVEC协处理支持 |
stacksize:任务堆栈大小;
main:任务入口函数;
arg1,…arg10:任务入口函数参数
下面来看一个具体的例子:
例1:创建任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/* includes */
#include "vxWorks.h"
#include "taskLib.h"
#include "sysLib.h"
int tid;
/* task function */
void myFunc(void)
{
int i;
printf("Hello, I am task %dn", taskIdSelf()); /* Print task Id */
for (i = 0; i < 10; i++)
{
printf("%d ", i);
taskDelay(sysClkRateGet ( ) / 2);
}
}
/* user entry */
void user_start()
{
printf("ready to begin a new taskn");
tid = taskSpawn("myTask", 90, VX_NO_STACK_FILL, 2000, (FUNCPTR) myFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
|
程序运行,在VxSim上输出:
1
2
|
Hello, I am task 14870080
0 1 2 3 4 5 6 7 8 9
|
taskDelay(sysClkRateGet ( ) / 2)语句的含义为将任务延迟0.5S,因此,0、1~9的数字输出之间间隔0.5S。
要特别注意taskSpawn函数的options参数,在如下几种情况下我们都要将其它options与 VX_FP_TASK做“按位或”操作使得任务支持浮点运算(如果仅包含此选项,则不需进行或操作):