基于嵌入式操作系统VxWorks的多任务并发程序设计(全) 联系客服

发布时间 : 星期三 文章基于嵌入式操作系统VxWorks的多任务并发程序设计(全)更新完毕开始阅读64db28244b35eefdc8d3330e

其中的n是要延迟的时间,以秒为单位。其中的sysClkRateGet(int ticks /* number of ticks every second */)函数返回系统的时钟速率,单位是tick数/每秒。操作系统每秒的tick数可以利用sysClkRateSet()函数设置。

5.4 挂起/恢复/重启任务

我们可以使用taskSuspend()函数挂起一个任务的运行,这个任务只有获得对应的taskResume()后才能再次运行,这两个API的原型为:

extern STATUS taskSuspend (int tid); extern STATUS taskResume (int tid);

例5:挂起/恢复任务

/* includes */ #include \#include \#include \ int tid;

/* task function */ void myFunc(void) { int i;

printf(\ for (i = 0; i < 10; i++) {

printf(\

taskDelay(sysClkRateGet() / 2); } }

/* suspend and resume task */ void suspendResumeMyTask(void) {

taskDelay(sysClkRateGet() *3); taskSuspend(tid);

printf(\ taskDelay(sysClkRateGet() *3); taskResume(tid); }

/* user entry */ void user_start() {

printf(\

tid = taskSpawn(\ taskSpawn(\

0, 0, 0, 0, 0, 0, 0, 0); }

运行输出:

Hello, I am task 17753664 0 1 2 3 4 5 my task is suspended 6 7 8 9

这个程序运行3秒后,suspendResumeMyTask任务挂起了myTask,输出“my task is suspended”。suspendResumeMyTask本身延迟3秒后恢复myTask,使得myTask再次输出“6 7 8 9”。显然,“6 7 8 9”与“0 1 2 3 4 5”的输出之间间隔了3秒以上的时间。 如果我们将上述程序改为: 例6:重启任务

/* includes */ #include \#include \#include \ int tid;

/* task function */ void myFunc(void) { int i;

printf(\ for (i = 0; i < 10; i++) {

printf(\

taskDelay(sysClkRateGet() / 2); } }

/* reset task */ void resetMyTask(void) {

taskDelay(sysClkRateGet() *3); printf(\ taskRestart(tid); }

/* user entry */ void user_start() {

printf(\

tid = taskSpawn(\

taskSpawn(\}

运行输出:

Hello, I am task 17753664

0 1 2 3 4 5 my task will be reseted Hello, I am task 17753664 0 1 2 3 4 5 6 7 8 9

我们可以使用taskRestart()函数重新启动一个任务,不管任务当前处于什么状态,它都会被重新开始。该API的原型是:

extern STATUS taskRestart (int tid);

在例6中,程序运行3秒后resetMyTask启动,它复位了myTask,因此myTask被重新执行,“Hello, I am task 17753664”以及“0 1 2 3 4 5”被再次输出。 5.5任务钩子

有过Windows钩子(Hook)编程经验的读者应该对其概念并不陌生,Hook作为回调函数,当被挂接后。操作系统发生特定的事情时,将触发这个Hook回调函数的执行。VxWorks也有钩子的概念,不过比Windows要简单许多,主要有taskCreateHook、taskDeleteHook、taskSwitchHookAdd,可以通过如下6个API来添加和删除这三种Hook:

STATUS taskCreateHookAdd (FUNCPTR createHook /* routine to be called when a task is created */ ); STATUS taskCreateHookDelete (FUNCPTR createHook /* routine to be deleted from list */); STATUS taskSwitchHookAdd (FUNCPTR switchHook /* routine to be called at every task switch */); STATUS taskSwitchHookDelete (FUNCPTR switchHook /* routine to be deleted from list */);

STATUS taskDeleteHookAdd (FUNCPTR deleteHook /* routine to be called when a task is deleted */); STATUS taskDeleteHookDelete (FUNCPTR deleteHook /* routine to be deleted from list */);

请看例程:

例7:任务钩子Hook

/* includes */ #include \#include \

#include \ //taskHook所对应的库

/* task function */ void myFunc(void) { int i;

printf(\}

/* taskCreatHook */ void myTaskHook(void) {

printf(\}

/* user entry */

void user_start() {

taskCreateHookAdd( (FUNCPTR) myTaskHook);

taskSpawn(\}

运行输出:

task hook function called Hello, I am task 14868640

5.6 其它重要API

与任务控制相关的其它重要API还有:

//设置任务优先级extern STATUS taskOptionsSet (int tid, int mask, int newOptions); //获得任务优先级extern STATUS taskOptionsGet (int tid, int *pOptions); //从任务ID获得任务名extern char * taskName (int tid); //从任务名获得任务IDextern int taskNameToId (char *name);

//确认ID为tid的任务是否存在extern STATUS taskIdVerify (int tid); //获得任务自身IDextern int taskIdSelf (void);

//任务状态是否为readyextern BOOL taskIsReady (int tid);

//任务状态是否为Suspendedextern BOOL taskIsSuspended (int tid); //获得任务的TCB指针extern WIND_TCB *taskTcb (int tid);

//获得任务的优先级STATUS taskPrioritySet (int tid, /* task ID */ int newPriority /* new priority */ );

//任务锁定与解锁:一个任务调用taskLock()后,任务运行时将没有基于优先级的抢占发生;而taskUnlock()则用于恢复锁定。extern STATUS taskLock (void); extern STATUS taskUnlock (void);

VxWorks支持两种方式的任务调度:

(1)基于优先级的抢占调度(Preemptive Priority Based Scheduling)

抢占是指正在执行的任务可以被打断,让另一个任务运行,它可以提高应用程序对异步事件的响应能力。基于优先级的抢占调度是最常见的抢占机制,用户任务被分配一个优先级,操作系统内核总是调度优先级最高的就绪任务运行于CPU。当系统正在执行低优先级任务时,一旦有更高优先级的任务准备就绪,OS内核会立即进行任务的上下文切换。

VxWorks的Wind内核划分优先级为256 级(0~255)。优先级0为最高优先级,优先级255为最低。当任务被创建时,系统根据用户指定的值分配任务优先级。VxWorks的任务优先级也可以是动态的,它们能在系统运行时被用户使用系统调用taskPrioritySet()来加以改变。 (2)时间片轮转调度(Round-Robin Scheduling)

时间片轮转调度指的是操作系统分配一定的时间间隔(时间片),使每个任务轮流运行于CPU。在VxWorks中,对于优先级相同的多个任务,如果状态为ready,则其可以通过时间片轮转方式公平享有CPU资源。

轮转调度法给处于就绪态的每个同优先级的任务分配一个相同的执行时间片,时间片的大小可由系统调用KernelTimeSlice指定。为对轮转调度进行支持,系统给每个任务提供一个运行时间计数器,任务运行时每一时间滴答计数器加1。一个任务用完时间片之后,OS停止执行该任务,将它放入就绪队列尾部,并将其运行时间计数器置零。接着,OS执行就绪队列中的下一个任务。 6. 任务调度 6.1时间片轮转调度

我们来看一个具体的例子,在这个程序中,用户启动了三个优先级相同的任务,并通过对kernelTimeSlice(TIMESLICE)的调用启动了时间片轮转调度。 例1:时间片轮转调度