基於嵌入式操作係統VxWorks的多任務並發程序設計(2) ――任務控製
4 任務與任務狀態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做“按位或”操作使得任務支持浮點運算(如果僅包含此選項,則不需進行或操作):
最後更新:2017-04-03 12:55:36