基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(全)_第1頁(yè)
基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(全)_第2頁(yè)
基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(全)_第3頁(yè)
基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(全)_第4頁(yè)
基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(全)_第5頁(yè)
已閱讀5頁(yè),還剩39頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1引言嵌入式系統(tǒng)定義為:嵌入到對(duì)象體系中的專用計(jì)算機(jī)系統(tǒng)。“嵌入性”、“專用性”與“計(jì)算機(jī)系統(tǒng)”是嵌入式系統(tǒng)的三個(gè)基本要素,對(duì)象系統(tǒng)則是指嵌入式系統(tǒng)所嵌入的宿主系統(tǒng)。目前,隨著高端消費(fèi)類電子產(chǎn)品(如PDA、手機(jī)、智能家電)的普及,嵌入式計(jì)算機(jī)系統(tǒng)獲得了相當(dāng)廣泛的應(yīng)用。操作系統(tǒng)在嵌入式軟件體系中占據(jù)著重要低位,學(xué)習(xí)和掌握相關(guān)的知識(shí)是一名嵌入式系統(tǒng)研發(fā)人員的必須。1.1本文的讀者對(duì)象與寫作目的本文針對(duì)的讀者對(duì)象為入門級(jí)的嵌入式系統(tǒng)軟件開發(fā)人員以及其他對(duì)嵌入式操作系統(tǒng)感興趣的朋友,順利閱讀本文需要讀者具備的基本知識(shí)能力為:(1)熟練的C語(yǔ)言程序設(shè)計(jì)能力;(2)操作系統(tǒng)的基本知識(shí)。如果讀者具備在Windows平臺(tái)下進(jìn)行多線程程序設(shè)計(jì)或者其他嵌入式操作系統(tǒng)本臺(tái)下進(jìn)行多任務(wù)程序設(shè)計(jì)的經(jīng)驗(yàn),將對(duì)閱讀本文有很大的幫助。本文雖然以VxWorks為介紹的主體對(duì)象,但是其中所論述的概念和方法并不局限于VxWorks操作系統(tǒng)本身。它們也同樣適用于其它嵌入式操作系統(tǒng),如WinCE、嵌入式Linux、ucos等,所謂“萬變不離其宗”。筆者力求能以通俗和形象的語(yǔ)言進(jìn)行論述,但是由于水平有限,文中難免存在錯(cuò)誤和紕漏,誠(chéng)盼讀者朋友指正。1.2為什么以VxWorks為寫作對(duì)象之所以選擇VxWorks操作系統(tǒng)為本文的寫作對(duì)象,是因?yàn)椋海?)VxWorks具備清晰的多任務(wù)并發(fā)控制及任務(wù)間通信的成熟機(jī)制;(2)VxWorks有廣泛的使用基礎(chǔ),國(guó)內(nèi)外分布著大量的VxWorks程序員;(3)VxWorks簡(jiǎn)單易學(xué),便于我們集中目標(biāo)講解多任務(wù)控制程序本身。1.3什么是VxWorksVxWorks操作系統(tǒng)是美國(guó)WindRiver公司于1983年設(shè)計(jì)開發(fā)的一種嵌入式實(shí)時(shí)操作系統(tǒng)(RTOS),它憑借著良好的可持續(xù)發(fā)展能力、高性能的內(nèi)核以及友好的用戶開發(fā)環(huán)境,在嵌入式實(shí)時(shí)操作系統(tǒng)領(lǐng)域占據(jù)了重要一席。VxWorks具備高可靠性和實(shí)時(shí)性,因而被廣泛地應(yīng)用在通信、軍事、航空、航天等高精尖技術(shù)及實(shí)時(shí)性要求極高的領(lǐng)域中,如衛(wèi)星通訊、軍事演習(xí)、彈道制導(dǎo)、飛機(jī)導(dǎo)航等。在美國(guó)的F-16、FA-18戰(zhàn)斗機(jī)、B-2隱形轟炸機(jī)和愛國(guó)者導(dǎo)彈上,甚至連1997年4月在火星表面登陸的火星探測(cè)器上也使用到了VxWorks。VxWorks的實(shí)時(shí)性體現(xiàn)在它能在限定時(shí)間內(nèi)執(zhí)行完規(guī)定的功能并對(duì)外部的異步事件作出響應(yīng)。實(shí)時(shí)操作系統(tǒng)主要應(yīng)用于過程控制、數(shù)據(jù)采集、通信、多媒體信息處理等對(duì)時(shí)間敏感的場(chǎng)合;而分時(shí)操作系統(tǒng)按照相等的時(shí)間片調(diào)度進(jìn)程輪流運(yùn)行,無法實(shí)時(shí)響應(yīng)外部異步事件,因而主要應(yīng)用于科學(xué)計(jì)算和實(shí)時(shí)性要求不高的場(chǎng)合。VxWorks由一個(gè)體積很小的內(nèi)核及一些可以根據(jù)需要進(jìn)行定制的系統(tǒng)模塊組成。VxWorks內(nèi)核最小為8KB,即便加上其它必要模塊,所占用的空間也很小,且不失其實(shí)時(shí)、多任務(wù)的系統(tǒng)特征。VxWorks的內(nèi)核主要包括:(1)多任務(wù):為滿足真實(shí)世界事件的異步性,現(xiàn)代操作系統(tǒng)需提供多任務(wù)支持,由系統(tǒng)內(nèi)核分配CPU給多個(gè)任務(wù)并發(fā)執(zhí)行。如果是單CPU,則執(zhí)行方式實(shí)質(zhì)是宏觀并行、微觀串行;(2)任務(wù)調(diào)度:真實(shí)世界的事件具有繼承的優(yōu)先級(jí),當(dāng)一個(gè)高優(yōu)先級(jí)的任務(wù)變?yōu)榭蓤?zhí)行態(tài),它會(huì)立即搶占當(dāng)前正在運(yùn)行的較低優(yōu)先級(jí)的任務(wù),VxWorks對(duì)這種優(yōu)先級(jí)搶占調(diào)度(PreemptivePriorityScheduling)提供了支持。同時(shí),VxWorks也支持同優(yōu)先級(jí)任務(wù)間的時(shí)間片輪轉(zhuǎn)調(diào)度(Round-RobinScheduling);(3)任務(wù)間的通訊與同步:在一個(gè)實(shí)時(shí)系統(tǒng)中,系統(tǒng)必須提供多個(gè)任務(wù)間快速且功能強(qiáng)大的通信機(jī)制,并提供為了有效地共享不可搶占的資源或臨界區(qū)所需的同步機(jī)制;(4)任務(wù)與中斷之間的通信:許多外設(shè)以中斷方式與CPU通信,我們不宜在中斷服務(wù)程序(ISR)中進(jìn)行過多的處理,通常將相應(yīng)處理交給特定任務(wù)去完成。VxWorks前些年對(duì)我國(guó)一直采取禁運(yùn)措施,自從對(duì)中國(guó)的銷售解禁以來,它在中國(guó)贏得了越來越多的用戶。2進(jìn)程、線程與任務(wù)既然我們是講解一種操作系統(tǒng),那我們就有必要再老生長(zhǎng)嘆一次進(jìn)程與線程的概念及其區(qū)別。進(jìn)程(Process)是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。程序只是一組指令的有序集合,它本身沒有任何運(yùn)行的含義,只是一個(gè)靜態(tài)實(shí)體。而進(jìn)程則不同,它是程序在某個(gè)數(shù)據(jù)集上的執(zhí)行,是一個(gè)動(dòng)態(tài)實(shí)體。它因創(chuàng)建而產(chǎn)生,因調(diào)度而運(yùn)行,因等待資源或事件而被處于等待狀態(tài),因完成任務(wù)而被撤消,反映了一個(gè)程序在一定的數(shù)據(jù)集上運(yùn)行的全部動(dòng)態(tài)過程。線程(Thread)是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位。線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制。線程和進(jìn)程的關(guān)系是:線程是屬于進(jìn)程的,線程運(yùn)行在進(jìn)程空間內(nèi),同一進(jìn)程所產(chǎn)生的線程共享同一內(nèi)存空間,當(dāng)進(jìn)程退出時(shí)該進(jìn)程所產(chǎn)生的線程都會(huì)被強(qiáng)制退出并清除。線程可與屬于同一進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源,但是其本身基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的信息(如程序計(jì)數(shù)器、一組寄存器和棧)。根據(jù)進(jìn)程與線程的設(shè)置,操作系統(tǒng)大致分為如下類型:(1)單進(jìn)程、單線程,MS-DOS大致是這種操作系統(tǒng);(2)多進(jìn)程、單線程,多數(shù)UNIX(及類UNIX的LINUX)是這種操作系統(tǒng);(3)多進(jìn)程、多線程,WindowsNT(以及基于NT內(nèi)核的Windows2000、XP等)、Solaris2.x和OS/2都是這種操作系統(tǒng);(4)單進(jìn)程、多線程,可以認(rèn)為VxWorks是這種操作系統(tǒng)。VxWorks只有一個(gè)進(jìn)程(內(nèi)存空間和資源分配),其任務(wù)的概念與線程大致相當(dāng),所有任務(wù)之間共享內(nèi)存和其它資源。3開發(fā)環(huán)境嵌入式軟件開發(fā)不同于PC機(jī)Windows操作系統(tǒng)之上的應(yīng)用軟件開發(fā),它一般需要一個(gè)交叉編譯和調(diào)試環(huán)境。編譯和調(diào)試軟件運(yùn)行在宿主機(jī)上(我們通常使用的PC機(jī),Windows操作系統(tǒng)),它們按照目標(biāo)平臺(tái)CPU指令集生成目標(biāo)代碼,并將目標(biāo)代碼下載到目標(biāo)機(jī)上運(yùn)行;此后,主機(jī)和目標(biāo)機(jī)需建立通訊連接,并傳輸調(diào)試命令和數(shù)據(jù)。調(diào)試方式如下圖所示:VxWorks的開發(fā)環(huán)境為WindRiver公司提供的Tornado,它支持的目標(biāo)平臺(tái)可以是X86、ARM、PowerPC等類型處理器。Tornado包含三個(gè)高度集成的部分:(1)運(yùn)行在宿主機(jī)和目標(biāo)機(jī)上的強(qiáng)有力的交叉開發(fā)工具和實(shí)用程序;(2)運(yùn)行在目標(biāo)機(jī)上的高性能、可裁剪的實(shí)時(shí)操作系統(tǒng)VxWorks;(3)連接宿主機(jī)和目標(biāo)機(jī)的多種通訊方式,如:以太網(wǎng),串口線,ICE或ROM仿真器等。對(duì)于不同的目標(biāo)機(jī),Tornado給開發(fā)者提供一個(gè)一致的圖形接口和人機(jī)界面,如下圖所示:我們通常需要一塊目標(biāo)電路板來進(jìn)行嵌入式系統(tǒng)的開發(fā)調(diào)試工作,但是相信還有相當(dāng)多的讀者朋友沒有目標(biāo)開發(fā)電路板,為了實(shí)現(xiàn)本文中代碼的調(diào)試,我們可采用兩種方式:(1)使用Tornado提供的VxSim模擬器來模擬調(diào)試,在此模擬器平臺(tái)上,我們同樣可以實(shí)現(xiàn)和運(yùn)行本文中將介紹的大部分程序。VxSim是一個(gè)原型仿真器,它能使開發(fā)者在沒有實(shí)際目標(biāo)硬件的情況下,先進(jìn)行原型機(jī)應(yīng)用程序的開發(fā)。如果我們要調(diào)試BSP程序,不能依賴此平臺(tái)。其界面很簡(jiǎn)潔,如下圖:(2)使用著名的VmWare虛擬機(jī)軟件虛擬一個(gè)X86目標(biāo)機(jī)平臺(tái),安裝對(duì)應(yīng)于X86版本的Tornado,我們可以調(diào)試BSP和一般應(yīng)用程序。VMWare是一個(gè)“虛擬機(jī)”軟件,它使用戶可以在一臺(tái)機(jī)器上同時(shí)運(yùn)行多個(gè)WIN2000/WINNT/WIN9X/DOS/LINUX/VxWorks等系統(tǒng)。VmWare是較“多啟動(dòng)”是一個(gè)更好的選擇:“多啟動(dòng)”系統(tǒng)在一個(gè)時(shí)刻只能運(yùn)行一個(gè)系統(tǒng),在系統(tǒng)切換時(shí)需要重新啟動(dòng)機(jī)器,而VmWare則使用運(yùn)行于Windows之上,各種操作系統(tǒng)的切換直接在VmWare軟件中進(jìn)行。VmWare的界面如下圖:4任務(wù)與任務(wù)狀態(tài)VxWorks實(shí)時(shí)內(nèi)核Wind提供了基本的多任務(wù)環(huán)境。對(duì)用戶而言,宏觀上看起來,多個(gè)任務(wù)同時(shí)在執(zhí)行。而本質(zhì)而言,在微觀上,系統(tǒng)內(nèi)核中的任務(wù)調(diào)度器總是在根據(jù)特定的調(diào)度策略讓它們交替運(yùn)行。系統(tǒng)調(diào)度器需要使用任務(wù)控制塊(TCB)數(shù)據(jù)結(jié)構(gòu)來管理任務(wù)調(diào)度功能,TCB被用來描述一個(gè)任務(wù)。TCB中存放了任務(wù)的上下文(context)信息,主要包括程序計(jì)數(shù)器PC、CPU內(nèi)部寄存器、浮點(diǎn)寄存器、堆棧指針SP、任務(wù)信息等。每一任務(wù)都與一個(gè)TCB關(guān)聯(lián),當(dāng)執(zhí)行中的任務(wù)被停止時(shí),任務(wù)的上下文信息需要被寫入TCB;而當(dāng)任務(wù)被重新執(zhí)行時(shí),必須要恢復(fù)這些上下文信息。VxWorks的一個(gè)任務(wù)可能處于如下幾種狀態(tài):Ready:就緒狀態(tài)(不是運(yùn)行狀態(tài)),其他資源已經(jīng)就緒,僅等待CPU,當(dāng)獲得CPU后,就進(jìn)入Running狀態(tài);Pended:阻塞狀態(tài),由于等待某些資源(CPU除外)而阻塞;Suspended:掛起狀態(tài),這種狀態(tài)需要用taskResume才能恢復(fù),主要用于調(diào)試。不會(huì)約束狀態(tài)的轉(zhuǎn)換,僅僅約束任務(wù)的執(zhí)行;Delayed:睡眠狀態(tài),任務(wù)以taskDelay主動(dòng)要求等待一段時(shí)間再執(zhí)行;這些狀態(tài)之間的轉(zhuǎn)換關(guān)系如下:任務(wù)狀態(tài)轉(zhuǎn)換完成方式Ready->pended通過semTake()/msgQReceive()調(diào)用Ready->delayed通過taskDelay()ready->suspended通過taskSuspend()pended->ready通過其它任務(wù)對(duì)semaGive()/msgQSend()的調(diào)用pended->suspended通過其它任務(wù)對(duì)taskSuspend()調(diào)用delayed->ready延遲期滿delayed->suspended通過taskSuspend()調(diào)用suspended->ready通過taskResume()/taskActivate()調(diào)用suspended->pended通過其它任務(wù)的taskResume()調(diào)用suspended->delayed通過其它任務(wù)的taskResume()調(diào)用5任務(wù)控制5.1創(chuàng)建任務(wù)VxWorks程序員創(chuàng)建任務(wù)需使用如下API:taskSpawn(char*name,intpriority,intoptions,intstackSize,

FUNCPTRentryPt,intarg1,intarg2,intarg3,

intarg4,intarg5,intarg6,intarg7,

intarg8,intarg9,intarg10);該API的參數(shù)定義如下:name:任務(wù)名;priority:任務(wù)優(yōu)先級(jí);options:任務(wù)選項(xiàng),下表給出了各種option及其含義:選項(xiàng)16進(jìn)制值含義VX_FP_TASK0x0008執(zhí)行浮點(diǎn)協(xié)處理VX_NO_STACK_FILL0x0100不對(duì)任務(wù)堆棧填充0xeeVX_PRIVATE_ENV0x0080執(zhí)行一個(gè)環(huán)境私有的任務(wù)VX_UNBREAKABLE0x0002使任務(wù)不能斷點(diǎn)VX_DSP_TASK0x02001=DSP協(xié)處理支持VX_ALTIVEC_TASK0x04001=ALTIVEC協(xié)處理支持stacksize:任務(wù)堆棧大?。籱ain:任務(wù)入口函數(shù);arg1,…arg10:任務(wù)入口函數(shù)參數(shù)下面來看一個(gè)具體的例子:例1:創(chuàng)建任務(wù)/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

printf("Hello,Iamtask%dn",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

/*userentry*/

voiduser_start()

{

printf("readytobeginanewtaskn");

tid=taskSpawn("myTask",90,VX_NO_STACK_FILL,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

}程序運(yùn)行,在VxSim上輸出:Hello,Iamtask14870080

0123456789taskDelay(sysClkRateGet()/2)語(yǔ)句的含義為將任務(wù)延遲0.5S,因此,0、1~9的數(shù)字輸出之間間隔0.5S。要特別注意taskSpawn函數(shù)的options參數(shù),在如下幾種情況下我們都要將其它options與VX_FP_TASK做“按位或”操作使得任務(wù)支持浮點(diǎn)運(yùn)算(如果僅包含此選項(xiàng),則不需進(jìn)行或操作):(1)執(zhí)行浮點(diǎn)操作;(2)調(diào)用返回任何浮點(diǎn)數(shù)的函數(shù);(3)調(diào)用參數(shù)為浮點(diǎn)數(shù)的函數(shù)。例如下列程序啟動(dòng)任務(wù)的方式就不正確:例2:創(chuàng)建浮點(diǎn)支持任務(wù)/*taskincludingfloatcalculate*/

voidfloatTask(void)

{

printf("%f",100/30.0);

}

/*userentry*/

voiduser_start()

{

taskSpawn("floatTask",90,VX_NO_STACK_FILL,2000,(FUNCPTR)floatTask,0,0,0,0,0,0,0,0,0,0);

}應(yīng)該將對(duì)taskSpawn函數(shù)調(diào)用的代碼改為:taskSpawn("floatTask",90,VX_NO_STACK_FILL|VX_FP_TASK,2000,floatTask,0,0,0,0,0,0,0,0,0,0);5.2終止任務(wù)exit():終止當(dāng)前任務(wù)。這個(gè)函數(shù)是不安全的,任務(wù)終止后,其所占據(jù)的內(nèi)存空間并未釋放,請(qǐng)看下面的程序:例3:任務(wù)退出/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

printf("Hello,Iamtask%dn",taskIdSelf());/*PrinttaskId*/

for(i=0;i<5;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

exit(0);

for(i=5;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

/*userentry*/

voiduser_start()

{

printf("readytobeginanewtaskn");

tid=taskSpawn("myTask",90,0x100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,

0);

}這次程序僅僅輸出:Hello,Iamtask14868640

01234這意味著exit(0)語(yǔ)句之后的循環(huán)for(i=5;i<10;i++)沒有被執(zhí)行。taskDelete()函數(shù):終止任務(wù)并釋放任務(wù)占用的內(nèi)存(堆棧和任務(wù)控制塊空間),其原型為:externSTATUStaskDelete(inttid);

參數(shù)tid為任務(wù)的ID。

請(qǐng)看下面的例子:例4:刪除任務(wù)/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

printf("Hello,Iamtask%dn",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

/*anothertaskfunction:deletemytask*/

voiddelMyTaskFunc(void)

{

taskDelay(sysClkRateGet()*4);

printf("readytodeletetaskn");

taskDelete(tid);

}

/*userentry*/

voiduser_start()

{

printf("readytobeginnewtasksn");

tid=taskSpawn("myTask",90,0x100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

taskSpawn("delMyTask",90,0x100,2000,(FUNCPTR)delMyTaskFunc,0,0,0,0,0,0,0,0,0,0);

}運(yùn)行輸出:Hello,Iamtask14868640

01234567readytobeginanewtask程序?yàn)檫\(yùn)行輸出8、9,這是因?yàn)樵诖酥?,myTask已經(jīng)被另一個(gè)任務(wù)――delMyTask刪除。任務(wù)可能被taskDelete()調(diào)用刪除掉,但這一行為也不一定是安全的。如果我們刪除一個(gè)獲得了某些資源(如二進(jìn)制信號(hào)量等)的任務(wù),則對(duì)應(yīng)的資源將不被釋放,到站其它正在等待該資源的任務(wù)永遠(yuǎn)不能獲得資源,系統(tǒng)會(huì)擋掉。我們可以用taskSafe()和taskUnsafe()來保護(hù)這種區(qū)域,例如:taskSafe();

semTake(semId,WAIT_FOREVER);

/*Blockuntilsemaphoreavailable*/

....criticalregion.

semGive(semId);semGive(semId);

/*Releasesemaphore*/

taskUnsafe();5.3延遲任務(wù)taskdelay()提供了一個(gè)簡(jiǎn)單的任務(wù)睡眠機(jī)制,常用于需要定時(shí)/延時(shí)機(jī)制的應(yīng)用中。它的原型是:STATUStaskDelay(intticks/*numberoftickstodelaytask*/);可以看出使用該函數(shù)實(shí)現(xiàn)延時(shí)的單位為節(jié)拍(tick)。在VxWorks下通常以如下方式調(diào)用taskDelay()函數(shù):taskDelay(sysClkRateGet()*n);其中的n是要延遲的時(shí)間,以秒為單位。其中的sysClkRateGet(intticks/*numberoftickseverysecond*/)函數(shù)返回系統(tǒng)的時(shí)鐘速率,單位是tick數(shù)/每秒。操作系統(tǒng)每秒的tick數(shù)可以利用sysClkRateSet()函數(shù)設(shè)置。5.4掛起/恢復(fù)/重啟任務(wù)我們可以使用taskSuspend()函數(shù)掛起一個(gè)任務(wù)的運(yùn)行,這個(gè)任務(wù)只有獲得對(duì)應(yīng)的taskResume()后才能再次運(yùn)行,這兩個(gè)API的原型為:externSTATUStaskSuspend(inttid);

externSTATUStaskResume(inttid);例5:掛起/恢復(fù)任務(wù)/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

printf("Hello,Iamtask%dn",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

/*suspendandresumetask*/

voidsuspendResumeMyTask(void)

{

taskDelay(sysClkRateGet()*3);

taskSuspend(tid);

printf("mytaskissuspendedn");

taskDelay(sysClkRateGet()*3);

taskResume(tid);

}

/*userentry*/

voiduser_start()

{

printf("readytobeginnewtasksn");

tid=taskSpawn("myTask",90,0x100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

taskSpawn("suspendResumeMyTask",90,0x100,2000,(FUNCPTR)suspendResumeMyTask,0,0,

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

}運(yùn)行輸出:Hello,Iamtask17753664

012345mytaskissuspended

6789這個(gè)程序運(yùn)行3秒后,suspendResumeMyTask任務(wù)掛起了myTask,輸出“mytaskissuspended”。suspendResumeMyTask本身延遲3秒后恢復(fù)myTask,使得myTask再次輸出“6789”。顯然,“6789”與“012345”的輸出之間間隔了3秒以上的時(shí)間。如果我們將上述程序改為:例6:重啟任務(wù)/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"sysLib.h"

inttid;

/*taskfunction*/

voidmyFunc(void)

{

inti;

printf("Hello,Iamtask%dn",taskIdSelf());/*PrinttaskId*/

for(i=0;i<10;i++)

{

printf("%d",i);

taskDelay(sysClkRateGet()/2);

}

}

/*resettask*/

voidresetMyTask(void)

{

taskDelay(sysClkRateGet()*3);

printf("mytaskwillberesetedn");

taskRestart(tid);

}

/*userentry*/

voiduser_start()

{

printf("readytobeginnewtasksn");

tid=taskSpawn("myTask",90,0x100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

taskSpawn("resetMyTask",90,0x100,2000,(FUNCPTR)resetMyTask,0,0,0,0,0,0,0,0,0,0);

}運(yùn)行輸出:Hello,Iamtask17753664

012345mytaskwillbereseted

Hello,Iamtask17753664

0123456789我們可以使用taskRestart()函數(shù)重新啟動(dòng)一個(gè)任務(wù),不管任務(wù)當(dāng)前處于什么狀態(tài),它都會(huì)被重新開始。該API的原型是:externSTATUStaskRestart(inttid);在例6中,程序運(yùn)行3秒后resetMyTask啟動(dòng),它復(fù)位了myTask,因此myTask被重新執(zhí)行,“Hello,Iamtask17753664”以及“012345”被再次輸出。5.5任務(wù)鉤子有過Windows鉤子(Hook)編程經(jīng)驗(yàn)的讀者應(yīng)該對(duì)其概念并不陌生,Hook作為回調(diào)函數(shù),當(dāng)被掛接后。操作系統(tǒng)發(fā)生特定的事情時(shí),將觸發(fā)這個(gè)Hook回調(diào)函數(shù)的執(zhí)行。VxWorks也有鉤子的概念,不過比Windows要簡(jiǎn)單許多,主要有taskCreateHook、taskDeleteHook、taskSwitchHookAdd,可以通過如下6個(gè)API來添加和刪除這三種Hook:STATUStaskCreateHookAdd(FUNCPTRcreateHook/*routinetobecalledwhenataskiscreated*/);

STATUStaskCreateHookDelete(FUNCPTRcreateHook/*routinetobedeletedfromlist*/);

STATUStaskSwitchHookAdd(FUNCPTRswitchHook/*routinetobecalledateverytaskswitch*/);

STATUStaskSwitchHookDelete(FUNCPTRswitchHook/*routinetobedeletedfromlist*/);

STATUStaskDeleteHookAdd(FUNCPTRdeleteHook/*routinetobecalledwhenataskisdeleted*/);

STATUStaskDeleteHookDelete(FUNCPTRdeleteHook/*routinetobedeletedfromlist*/);請(qǐng)看例程:例7:任務(wù)鉤子Hook/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"taskHookLib.h"http://taskHook所對(duì)應(yīng)的庫(kù)

/*taskfunction*/

voidmyFunc(void)

{

inti;

printf("Hello,Iamtask%dn",taskIdSelf());/*PrinttaskId*/

}

/*taskCreatHook*/

voidmyTaskHook(void)

{

printf("taskhookfunctioncalledn");

}

/*userentry*/

voiduser_start()

{

taskCreateHookAdd((FUNCPTR)myTaskHook);

taskSpawn("myTask",90,0x100,2000,(FUNCPTR)myFunc,0,0,0,0,0,0,0,0,0,0);

}運(yùn)行輸出:taskhookfunctioncalled

Hello,Iamtask148686405.6其它重要API與任務(wù)控制相關(guān)的其它重要API還有://設(shè)置任務(wù)優(yōu)先級(jí)externSTATUStaskOptionsSet(inttid,intmask,intnewOptions);

//獲得任務(wù)優(yōu)先級(jí)externSTATUStaskOptionsGet(inttid,int*pOptions);

//從任務(wù)ID獲得任務(wù)名externchar*taskName(inttid);

//從任務(wù)名獲得任務(wù)IDexterninttaskNameToId(char*name);

//確認(rèn)ID為tid的任務(wù)是否存在externSTATUStaskIdVerify(inttid);

//獲得任務(wù)自身IDexterninttaskIdSelf(void);

//任務(wù)狀態(tài)是否為readyexternBOOLtaskIsReady(inttid);

//任務(wù)狀態(tài)是否為SuspendedexternBOOLtaskIsSuspended(inttid);

//獲得任務(wù)的TCB指針externWIND_TCB*taskTcb(inttid);

//獲得任務(wù)的優(yōu)先級(jí)STATUStaskPrioritySet(inttid,/*taskID*/intnewPriority/*newpriority*/);

//任務(wù)鎖定與解鎖:一個(gè)任務(wù)調(diào)用taskLock()后,任務(wù)運(yùn)行時(shí)將沒有基于優(yōu)先級(jí)的搶占發(fā)生;而taskUnlock()則用于恢復(fù)鎖定。externSTATUStaskLock(void);

externSTATUStaskUnlock(void);VxWorks支持兩種方式的任務(wù)調(diào)度:(1)基于優(yōu)先級(jí)的搶占調(diào)度(PreemptivePriorityBasedScheduling)搶占是指正在執(zhí)行的任務(wù)可以被打斷,讓另一個(gè)任務(wù)運(yùn)行,它可以提高應(yīng)用程序?qū)Ξ惒绞录捻憫?yīng)能力。基于優(yōu)先級(jí)的搶占調(diào)度是最常見的搶占機(jī)制,用戶任務(wù)被分配一個(gè)優(yōu)先級(jí),操作系統(tǒng)內(nèi)核總是調(diào)度優(yōu)先級(jí)最高的就緒任務(wù)運(yùn)行于CPU。當(dāng)系統(tǒng)正在執(zhí)行低優(yōu)先級(jí)任務(wù)時(shí),一旦有更高優(yōu)先級(jí)的任務(wù)準(zhǔn)備就緒,OS內(nèi)核會(huì)立即進(jìn)行任務(wù)的上下文切換。VxWorks的Wind內(nèi)核劃分優(yōu)先級(jí)為256級(jí)(0~255)。優(yōu)先級(jí)0為最高優(yōu)先級(jí),優(yōu)先級(jí)255為最低。當(dāng)任務(wù)被創(chuàng)建時(shí),系統(tǒng)根據(jù)用戶指定的值分配任務(wù)優(yōu)先級(jí)。VxWorks的任務(wù)優(yōu)先級(jí)也可以是動(dòng)態(tài)的,它們能在系統(tǒng)運(yùn)行時(shí)被用戶使用系統(tǒng)調(diào)用taskPrioritySet()來加以改變。(2)時(shí)間片輪轉(zhuǎn)調(diào)度(Round-RobinScheduling)時(shí)間片輪轉(zhuǎn)調(diào)度指的是操作系統(tǒng)分配一定的時(shí)間間隔(時(shí)間片),使每個(gè)任務(wù)輪流運(yùn)行于CPU。在VxWorks中,對(duì)于優(yōu)先級(jí)相同的多個(gè)任務(wù),如果狀態(tài)為ready,則其可以通過時(shí)間片輪轉(zhuǎn)方式公平享有CPU資源。輪轉(zhuǎn)調(diào)度法給處于就緒態(tài)的每個(gè)同優(yōu)先級(jí)的任務(wù)分配一個(gè)相同的執(zhí)行時(shí)間片,時(shí)間片的大小可由系統(tǒng)調(diào)用KernelTimeSlice指定。為對(duì)輪轉(zhuǎn)調(diào)度進(jìn)行支持,系統(tǒng)給每個(gè)任務(wù)提供一個(gè)運(yùn)行時(shí)間計(jì)數(shù)器,任務(wù)運(yùn)行時(shí)每一時(shí)間滴答計(jì)數(shù)器加1。一個(gè)任務(wù)用完時(shí)間片之后,OS停止執(zhí)行該任務(wù),將它放入就緒隊(duì)列尾部,并將其運(yùn)行時(shí)間計(jì)數(shù)器置零。接著,OS執(zhí)行就緒隊(duì)列中的下一個(gè)任務(wù)。6.任務(wù)調(diào)度6.1時(shí)間片輪轉(zhuǎn)調(diào)度我們來看一個(gè)具體的例子,在這個(gè)程序中,用戶啟動(dòng)了三個(gè)優(yōu)先級(jí)相同的任務(wù),并通過對(duì)kernelTimeSlice(TIMESLICE)的調(diào)用啟動(dòng)了時(shí)間片輪轉(zhuǎn)調(diào)度。例1:時(shí)間片輪轉(zhuǎn)調(diào)度/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"kernelLib.h"

#include"sysLib.h"

/*functionprototypes*/

voidtaskOne(void);

voidtaskTwo(void);

voidtaskThree(void);

/*globals*/

#defineITER1100

#defineITER210

#definePRIORITY101

#defineTIMESLICEsysClkRateGet()

#defineLONG_TIME0xFFFFFFL

voidsched(void)/*functiontocreatethethreetasks*/

{

inttaskIdOne,taskIdTwo,taskIdThree;

if(kernelTimeSlice(TIMESLICE)==OK)

/*turnround-robinon*/

printf("nnnntttTIMESLICE=%dsecondsnnn",TIMESLICE/60);

/*spawnthethreetasks*/

if((taskIdOne=taskSpawn("task1",PRIORITY,0x100,20000,(FUNCPTR)taskOne,

0,0,0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskOnefailedn");

if((taskIdTwo=taskSpawn("task2",PRIORITY,0x100,20000,(FUNCPTR)taskTwo,

0,0,0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskTwofailedn");

if((taskIdThree=taskSpawn("task3",PRIORITY,0x100,20000,(FUNCPTR)

taskThree,0,0,0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskThreefailedn");

}

voidtaskOne(void)

{

unsignedinti,j;

for(i=0;i<ITER1;i++)

{

for(j=0;j<ITER2;j++)

printf("task1n");

/*logmessages*/

for(j=0;j<LONG_TIME;j++)

;

/*allowtimeforcontextswitch*/

}

}

voidtaskTwo(void)

{

unsignedinti,j;

for(i=0;i<ITER1;i++)

{

for(j=0;j<ITER2;j++)

printf("task2n");

/*logmessages*/

for(j=0;j<LONG_TIME;j++)

;

/*allowtimeforcontextswitch*/

}

}

voidtaskThree(void)

{

unsignedinti,j;

for(i=0;i<ITER1;i++)

{

for(j=0;j<ITER2;j++)

printf("task3n");

/*logmessages*/

for(j=0;j<LONG_TIME;j++)

;

/*allowtimeforcontextswitch*/

}

}程序運(yùn)行輸出:一會(huì)兒輸出一些“task1”,一會(huì)兒輸出一些“task2”,再一會(huì)兒輸出一些“task3”。每次輸出了某任務(wù)的一部分內(nèi)容后,就開始輸出另一任務(wù)的內(nèi)容,這說明了task1、task2、task3再進(jìn)行時(shí)間片輪轉(zhuǎn)切換。對(duì)于任務(wù)的上下文切換,我們可以使用WindView進(jìn)行觀察。WindView是一個(gè)圖形化的動(dòng)態(tài)診斷和分析工具,它可以向開發(fā)者提供目標(biāo)機(jī)硬件上所運(yùn)行應(yīng)用程序的許多詳細(xì)情況。下圖顯示了使用WindView獲取的上述程序的運(yùn)行結(jié)果:kernelTimeSlice()的函數(shù)原型為:STATUSkernelTimeSlice(intticks/*time-sliceinticksor0todisableround-robin*/);程序中的kernelTimeSlice(TIMESLICE)展開后為kernelTimeSlice(sysClkRateGet()),即每秒鐘進(jìn)行一次輪轉(zhuǎn)。如果kernelTimeSlice函數(shù)中的輸入?yún)?shù)為0,時(shí)間片輪轉(zhuǎn)調(diào)度就不會(huì)發(fā)生,程序的輸出將是:先輸出ITER1*ITER2個(gè)“task1”,再輸出ITER1*ITER2個(gè)“task2”,最后輸出ITER1*ITER2個(gè)“task3”。6.2優(yōu)先級(jí)搶占調(diào)度如果將例1中三個(gè)任務(wù)的優(yōu)先級(jí)設(shè)置的不相同,即將程序改為:例2:優(yōu)先級(jí)搶占調(diào)度/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"kernelLib.h"

#include"sysLib.h"

/*functionprototypes*/

voidtaskOne(void);

voidtaskTwo(void);

voidtaskThree(void);

/*globals*/

#defineITER1100

#defineITER210

#defineHIGH100/*highpriority*/

#defineMID101/*mediumpriority*/

#defineLOW102/*lowpriority*/

#defineLONG_TIME0xFFFFFFL

voidsched(void)/*functiontocreatethetwotasks*/

{

inttaskIdOne,taskIdTwo,taskIdThree;

printf("nnnnn");

/*spawnthethreetasks*/

if((taskIdOne=taskSpawn("task1",LOW,0x100,20000,(FUNCPTR)taskOne,0,0,

0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskOnefailedn");

if((taskIdTwo=taskSpawn("task2",MID,0x100,20000,(FUNCPTR)taskTwo,0,0,

0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskTwofailedn");

if((taskIdThree=taskSpawn("task3",HIGH,0x100,20000,(FUNCPTR)taskThree,

0,0,0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskThreefailedn");

}

voidtaskOne(void)

{

…//samewithexample1

}

voidtaskTwo(void)

{

…//samewithexample1

}

voidtaskThree(void)

{

…//samewithexample1

}再觀察程序的運(yùn)行結(jié)果為:先輸出ITER1*ITER2個(gè)“task3”,再輸出ITER1*ITER2個(gè)“task2”,最后輸出ITER1*ITER2個(gè)“task1”。這是因?yàn)閠ask1、task2、task3的優(yōu)先級(jí)順序是“task3-task2-task1”,故在task3執(zhí)行完(或被阻塞、掛起)前,task2得不到執(zhí)行;同理,在在task2執(zhí)行完(或被阻塞、掛起)前,task1也得不到執(zhí)行。6.3改變?nèi)蝿?wù)的優(yōu)先級(jí)在VxWorks中,我們可以使用taskPrioritySet()函數(shù)來動(dòng)態(tài)改變?nèi)蝿?wù)的優(yōu)先級(jí),這個(gè)函數(shù)的原型是:STATUStaskPrioritySet(inttid,/*taskID*/intnewPriority/*newpriority*/);我們將例2的程序修改,在其中增加task4,task4延遲100毫秒后,將task1的優(yōu)先級(jí)設(shè)置到最高:例3:改變?nèi)蝿?wù)的優(yōu)先級(jí)/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

/*functionprototypes*/

voidtaskOne(void);

voidtaskTwo(void);

voidtaskThree(void);

voidtaskFour(void);

/*globals*/

#defineITER1100

#defineITER21

#defineLONG_TIME1000000

#defineHIGH100/*highpriority*/

#defineMID101/*mediumpriority*/

#defineLOW102/*lowpriority*/

#defineTIMESLICEsysClkRateGet()

inttaskIdOne,taskIdTwo,taskIdThree;

voidsched(void)/*functiontocreatethetwotasks*/

{

printf("nnnnn");

/*spawnthefourtasks*/

if((taskIdOne=taskSpawn("task1",LOW,0x100,20000,(FUNCPTR)taskOne,0,0,

0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskOnefailedn");

if((taskIdTwo=taskSpawn("task2",MID,0x100,20000,(FUNCPTR)taskTwo,0,0,

0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskTwofailedn");

if((taskIdThree=taskSpawn("task3",HIGH,0x100,20000,(FUNCPTR)taskThree,

0,0,0,0,0,0,0,0,0,0))==ERROR)

printf("taskSpawntaskThreefailedn");

if(taskSpawn("task4",HIGH,0x100,20000,(FUNCPTR)taskFour,0,0,0,0,0,

0,0,0,0,0)==ERROR)

printf("taskSpawntaskFourfailedn");

}

voidtaskOne(void)

{

…//samewithexample1

}

voidtaskTwo(void)

{

…//samewithexample1

}

voidtaskThree(void)

{

…//samewithexample1

}

voidtaskFour(void)

{

taskDelay(TIMESLICE/10);

taskPrioritySet(taskIdOne,HIGH-1);

}在task2任務(wù)運(yùn)行輸出“task2”的過程中,task1搶占了task2的CPU資源,先是輸出了所有的“task1”,最后剩余的“task2”得以輸出。我們用WINDVIEW捕獲上述程序中各任務(wù)切換的運(yùn)行軌跡VxWorks提供了多種任務(wù)間通信方式,主要有:(1)共享內(nèi)存(SharedMemory),用于簡(jiǎn)單的數(shù)據(jù)共享;由于VxWorks的所有任務(wù)存在于單一的線性地址空間,所以任務(wù)間可共享數(shù)據(jù),全局變量、線性隊(duì)列、環(huán)形隊(duì)列、鏈表、指針都可被具有不同上下文的任務(wù)訪問。(2)信號(hào)量(Semaphore),用于互斥和同步;信號(hào)量是VxWorks所提供的最快速的任務(wù)間通信機(jī)制,它主要用于解決任務(wù)間共享資源的互斥訪問和同步。針對(duì)問題的不同類型,VxWorks提供了三種信號(hào)量:二進(jìn)制(binary)信號(hào)量、互斥(mutualexclusion)信號(hào)量、計(jì)數(shù)(counting)信號(hào)量。二進(jìn)制信號(hào)量和互斥信號(hào)量只能處于0和1兩種狀態(tài),可以看作計(jì)數(shù)值為1的計(jì)數(shù)信號(hào)量。二進(jìn)制信號(hào)量可用于同步與互斥,而互斥信號(hào)量只能用于互斥,但其支持優(yōu)先級(jí)繼承機(jī)制。(3)消息隊(duì)列(Messagequeues)和管道(Pipe),單CPU內(nèi)任務(wù)間的信息傳送;消息機(jī)制使用一個(gè)被各有關(guān)進(jìn)程共享的消息隊(duì)列,任務(wù)之間經(jīng)由這個(gè)消息隊(duì)列發(fā)送和接收消息。管道則是受驅(qū)動(dòng)器pipeDrv管理的虛擬I/O設(shè)備,它提供了一種靈活的消息傳送機(jī)制。任務(wù)能調(diào)用標(biāo)準(zhǔn)的I/O函數(shù)打開、讀出、寫入管道。(4)套接字(Socket)和遠(yuǎn)程過程調(diào)用(RPC),用于網(wǎng)絡(luò)間任務(wù)消息傳送;與其它操作系統(tǒng)一樣,Vxworks和網(wǎng)絡(luò)協(xié)議的接口靠套接字來實(shí)現(xiàn),套接字可實(shí)現(xiàn)運(yùn)行在VxWorks系統(tǒng)或其它系統(tǒng)之間任務(wù)的信息傳送。遠(yuǎn)程過程調(diào)用允許任務(wù)調(diào)用另一運(yùn)行VxWorks或其它系統(tǒng)的主機(jī)上的過程。(5)信號(hào)(Signals),用于異常處理(Exceptionhandling)。7.任務(wù)間通信7.1信號(hào)量VxWorks主要提供如下API進(jìn)行信號(hào)量的創(chuàng)建、獲取和釋放:(1)semBCreate():分配并初始化一個(gè)二進(jìn)制信號(hào)量,函數(shù)原型為:SEM_IDsemBCreate

(

intoptions,/*信號(hào)量選項(xiàng)*/

SEM_B_STATEinitialState/*信號(hào)量初始化狀態(tài)值*/

);(2)semMCreate():分配并初始化一個(gè)互斥信號(hào)量,函數(shù)原型為:SEM_IDsemBCreate

(

intoptions,/*信號(hào)量選項(xiàng)*/

SEM_B_STATEinitialState/*信號(hào)量初始化狀態(tài)值*/

);(3)semCCreate():分配并初始化一個(gè)計(jì)數(shù)信號(hào)量,函數(shù)原型為:SEM_IDsemCCreate

(

intoptions,/*信號(hào)量選項(xiàng)*/

intinitialCount/*信號(hào)量初始計(jì)數(shù)值*/

);當(dāng)一個(gè)信號(hào)量被創(chuàng)建時(shí),它的隊(duì)列(queue)類型需要被確定。等待信號(hào)量的任務(wù)隊(duì)列可以以優(yōu)先級(jí)順序(SEM_Q_PRIORITY)或者先到先得方式(SEM_Q_FIFO)排列。(4)semDelete():刪除一個(gè)自由的信號(hào)量,函數(shù)原型為:STATUSsemDelete

(

SEM_IDsemId/*要?jiǎng)h除的信號(hào)量ID號(hào)*/

);

(5)semTake():占有一個(gè)信號(hào)量,函數(shù)原型為:

STATUSsemTake

(

SEM_IDsemId/*所要得到的信號(hào)量ID號(hào)*/

inttimeout/*等待時(shí)間*/

);

(6)semGive():釋放一個(gè)信號(hào)量,函數(shù)原型為:

STATUSsemGive

(

SEM_IDsemId/*所給出的信號(hào)量ID號(hào)*/

);

(7)semFlush():解鎖所有等待信號(hào)量的任務(wù),函數(shù)原型為:

STATUSsemFlush

(

SEM_IDsemId/*要解鎖的信號(hào)量ID號(hào)*/

);7.1.1二進(jìn)制信號(hào)量例1:二進(jìn)制信號(hào)量/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"semLib.h"

#include"stdio.h"

/*functionprototypes*/

voidtaskOne(void);

voidtaskTwo(void);

/*globals*/

#defineITER10

SEM_IDsemBinary;

intglobal=0;

voidbinary(void)

{

inttaskIdOne,taskIdTwo;

/*createsemaphorewithsemaphoreavailableandqueuetasksonFIFObasis*/

semBinary=semBCreate(SEM_Q_FIFO,SEM_FULL);

/*Note1:lockthesemaphoreforschedulingpurposes*/

semTake(semBinary,WAIT_FOREVER);

/*spawnthetwotasks*/

taskIdOne=taskSpawn("t1",90,0x100,2000,(FUNCPTR)taskOne,0,0,0,0,0,0,0,0,0,0);

taskIdTwo=taskSpawn("t2",90,0x100,2000,(FUNCPTR)taskTwo,0,0,0,0,0,0,0,0,0,0);

}

voidtaskOne(void)

{

inti;

for(i=0;i<ITER;i++)

{

semTake(semBinary,WAIT_FOREVER);/*waitindefinitelyforsemaphore*/

printf("IamtaskOneandglobal=%dn",++global);

semGive(semBinary);/*giveupsemaphore*/

}

}

voidtaskTwo(void)

{

inti;

semGive(semBinary);/*Note2:giveupsemaphore(aschedulingfix)*/

for(i=0;i<ITER;i++)

{

semTake(semBinary,WAIT_FOREVER);/*waitindefinitelyforsemaphore*/

printf("IamtaskTwoandglobal=%dn",--global);

semGive(semBinary);/*giveupsemaphore*/

}

}上述程序通過semTake和semGive保護(hù)每次使用printf輸出一串信息時(shí)不被間斷。要?jiǎng)?chuàng)建一個(gè)發(fā)揮互斥作用的二進(jìn)制信號(hào)量一般使用semBCreat(xxx,SEM_FULL)調(diào)用,其中的SEM_FULL暗示該信號(hào)量用于任務(wù)間的互斥(最開始二進(jìn)制信號(hào)量可獲得)。對(duì)臨界區(qū)域(criticalregion)的訪問需以semTake和semGive加以保護(hù):semTake(semMutex,WAIT_FOREVER);

../*criticalregion,onlyaccessiblebyasingletaskatatime*/

semGive(semMutex);要?jiǎng)?chuàng)建一個(gè)發(fā)揮同步作用的二進(jìn)制信號(hào)量一般使用semBCreat(xxx,SEM_EMPTY)調(diào)用,其中的SEM_EMPTY暗示該信號(hào)量用于任務(wù)間的同步(即最開始二進(jìn)制信號(hào)量不可獲得)。二進(jìn)制信號(hào)量使用最廣泛的一種情況是中斷與任務(wù)間通信。中斷服務(wù)程序一般以二進(jìn)制信號(hào)量“通知”對(duì)應(yīng)的任務(wù)進(jìn)行中斷后的處理工作,例如:SEM_IDsyncSem;/*IDofsyncsemaphore*/

myTask(void)

{

semTake(syncSem,WAIT_FOREVER);/*waitforeventtooccur*/

printf("myTaskgotthesemaphoren");

.../*processevent*/

}

eventInterruptSvcRout(void)

{

semGive(syncSem);/*letmyTaskprocessevent*/

...

}7.1.2互斥信號(hào)量互斥信號(hào)量可以看作一種特殊的二進(jìn)制信號(hào)量,其支持普通二進(jìn)制信號(hào)量不支持的一些特性,提供優(yōu)先級(jí)繼承、安全刪除和回歸能力?;コ庑盘?hào)量的使用方法和二進(jìn)制信號(hào)量基本類似,但有如下區(qū)別:(1)僅僅被用做互斥,不能提供同步機(jī)制;(2)只能被使用它的任務(wù)釋放;(3)中斷服務(wù)程序(ISR)不能釋放它;(4)不能使用函數(shù)semFlush();(5)支持使用二進(jìn)制信號(hào)量進(jìn)行互斥時(shí)所不支持的優(yōu)先級(jí)“翻轉(zhuǎn)”。任務(wù)的優(yōu)先級(jí)翻轉(zhuǎn)是指高優(yōu)先級(jí)任務(wù)因等待低優(yōu)先級(jí)任務(wù)占用的互斥資源而被較低優(yōu)先級(jí)(高于低優(yōu)先級(jí)但低于高優(yōu)先級(jí))的任務(wù)不斷搶占的情況。VxWorks操作系統(tǒng)提供優(yōu)先級(jí)繼承機(jī)制對(duì)優(yōu)先級(jí)翻轉(zhuǎn)進(jìn)行預(yù)防。占用互斥資源但優(yōu)先級(jí)較低的任務(wù)被暫時(shí)地提高到等待該資源的最高優(yōu)先級(jí)任務(wù)的優(yōu)先級(jí)。這樣,中等優(yōu)先級(jí)的任務(wù)將無法搶占原本低優(yōu)先級(jí)的任務(wù),使得低優(yōu)先級(jí)任務(wù)能盡快執(zhí)行,釋放出優(yōu)先級(jí)較高的任務(wù)所需要的資源。為了使互斥信號(hào)量支持優(yōu)先級(jí)繼承支持,我們?cè)谡{(diào)用semMCreate時(shí)應(yīng)使用SEM_Q_PRIORITY和SEM_INVERSION_SAFE選項(xiàng)?;コ庑盘?hào)量提供互斥也需要對(duì)臨界區(qū)域進(jìn)行保護(hù):semTake(semMutex,WAIT_FOREVER);

..//criticalregion,onlyaccessiblebyasingletaskatatime.

semGive(semMutex);8.消息隊(duì)列和管道VxWorks主要提供如下API進(jìn)行消息隊(duì)列的創(chuàng)建、讀取和傳遞:msgQCreate():創(chuàng)建斌初始化一個(gè)消息隊(duì)列,函數(shù)原型為:MSG_Q_IDmsgQCreate

(

intmaxMsgs,/*隊(duì)列所能容納的最大消息數(shù)目*/

intmaxMsgLength,/*每一消息的最大長(zhǎng)度*/

intoptions/*消息入列方式*/

);

msgQDelete():終止并釋放一個(gè)消息隊(duì)列,函數(shù)原型為:

STATUSmsgQDelete

(

MSG_Q_IDmsgQId/*要?jiǎng)h除的消息隊(duì)列ID號(hào)*/

);

msgQSend():發(fā)送一個(gè)消息到消息隊(duì)列,函數(shù)原型為:

STATUSmsgQSend

(

MSG_Q_IDmsgQId,/*所發(fā)向的消息隊(duì)列名*/

char*buffer,/*消息包所在緩沖區(qū)指針*/

UINTnBytes,/*消息包長(zhǎng)度*/

inttimeout,/*等待的時(shí)間長(zhǎng)度*/

intpriority/*優(yōu)先級(jí)*/

);

msgQReceive():從消息隊(duì)列接受一個(gè)消息,函數(shù)原型為:

intmsgQReceive

(

MSG_Q_IDmsgQId,/*接收消息的消息隊(duì)列ID號(hào)*/

char*buffer,/*接收消息的緩沖區(qū)指針*/

UINTmaxNBytes,/*緩沖區(qū)長(zhǎng)度*/

inttimeout/*等待時(shí)間*/

);下面我們以著名的生產(chǎn)者/消費(fèi)者問題作為例子來說明消息隊(duì)列的用途:例2:消息隊(duì)列/*includes*/

#include"vxWorks.h"

#include"taskLib.h"

#include"msgQLib.h"

#include"sysLib.h"

#include"stdio.h"

/*globals*/

#defineCONSUMER_TASK_PRI99/*Priorityoftheconsumertask*/

#definePRODUCER_TASK_PRI98/*Priorityoftheproducertask*/

#defineTASK_STACK_SIZE5000/*stacksizeforspawnedtasks*/

structmsg{/*datastructureformsgpassing*/

inttid;/*taskid*/

intvalue;/*msgvalue*/

};

LOCALMSG_Q_IDmsgQId;/*messagequeueid*/

LOCALintnumMsg=8;/*numberofmessages*/

LOCALBOOLnotDone;/*Flagtoindicatethecompletion*/

/*functionprototypes*/

LOCALvoidproducerTask();/*producertask*/

LOCALvoidconsumerTask();/*consumertask*/

/*userentry*/

voidmsgQDemo()

{

notDone=TRUE;/*initializetheglobalflag*/

/*Createthemessagequeue*/

if((msgQId=msgQCreate(numMsg,sizeof(structmsg),MSG_Q_FIFO))==NULL)

{

perror("ErrorincreatingmsgQ");

}

/*SpawntheproducerTasktask*/

if(taskSpawn("tProducerTask",PRODUCER_TASK_PRI,0,TASK_STACK_SIZE,(FUNCPTR)producerTask,0,0,0,0,0,0,0,0,0,0)==ERROR)

{

perror("producerTask:ErrorinspawningdemoTask");

}

/*SpawntheconsumerTasktask*/

if(taskSpawn("tConsumerTask",CONSUMER_TASK_PRI,0,TASK_STACK_SIZE,(FUNCPTR)consumerTask,0,0,0,0,0,0,0,0,0,0)==ERROR)

{

perror("consumerTask:ErrorinspawningdemoTask");

}

/*pollingisnotrecommended.Butusedtomakethisdemonstrationsimple*/

while(notDone)

taskDelay(sysClkRateGet());

if(msgQDelete(msgQId)==ERROR)

{

perror("ErrorindeletingmsgQ");

}

}

/*producerTask:發(fā)送消息給consumerTask*/

voidproducerTask(void)

{

intcount;

intvalue;

structmsgproducedItem;/*produceritem-produceddata*/

printf("producerTaskstarted:taskid=%#xn",taskIdSelf());

/*ProducenumMsgnumberofmessagesandsendthesemessages*/

for(count=1;count<=numMsg;count++)

{

value=count*10;/*produceavalue*/

/*Fillinthedatastructureformessagepassing*/

producedItem.tid=taskIdSelf();

producedItem.value=value;

/*SendMessages*/

if((msgQSend(msgQId,(char*)&producedItem,sizeof(producedItem),

WAIT_FOREVER,MSG_PRI_NORMAL))==ERROR)

{

perror("Errorinsendingthemessage");

}

else

printf("ProducerTask:tid=%#x,producedvalue=%dn",taskIdSelf(),

value);

}

}

/*consumerTask:獲取(消費(fèi))消息*/

voidconsumerTask(void)

{

intcount;

structmsgconsumedItem;/*consumeritem-consumeddata*/

printf("nnConsumerTask:Started-taskid=%#xn",taskIdSelf());

/*consumenumMsgnumberofmessages*/

for(count=1;count<=numMsg;count++)

{

/*Receivemessages*/

if((msgQ

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論