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

下載本文檔

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

文檔簡(jiǎn)介

基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(1)基本概念02月 13th, 2006 by 宋寶華 作者:宋寶華 e-mail:21 出處:軟件報(bào)(轉(zhuǎn)載請(qǐng)務(wù)必注明作者與出處) 1引言 嵌入式系統(tǒng)定義為:嵌入到對(duì)象體系中的專用計(jì)算機(jī)系統(tǒng)?!扒度胄浴薄ⅰ皩S眯浴迸c“計(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語言程序設(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等,所謂“萬變不離其宗”。 筆者力求能以通俗和形象的語言進(jìn)行論述,但是由于水平有限,文中難免存在錯(cuò)誤和紕漏,誠(chéng)盼讀者朋友指正。 1.2 為什么以VxWorks為寫作對(duì)象 之所以選擇VxWorks操作系統(tǒng)為本文的寫作對(duì)象,是因?yàn)椋?(1)VxWorks具備清晰的多任務(wù)并發(fā)控制及任務(wù)間通信的成熟機(jī)制; (2)VxWorks有廣泛的使用基礎(chǔ),國(guó)內(nèi)外分布著大量的VxWorks程序員; (3)VxWorks簡(jiǎn)單易學(xué),便于我們集中目標(biāo)講解多任務(wù)控制程序本身。 1.3 什么是VxWorks VxWorks操作系統(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)度(Preemptive Priority Scheduling)提供了支持。同時(shí),VxWorks也支持同優(yōu)先級(jí)任務(wù)間的時(shí)間片輪轉(zhuǎn)調(diào)度(Round-Robin Scheduling); (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)程、多線程,Windows NT(以及基于NT內(nèi)核的Windows 2000、XP等)、Solaris 2.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的界面如下圖:Posted in 3.嵌入式系統(tǒng) | No Comments 基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(2)任務(wù)控制03月 5th, 2006 by 宋寶華 基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(2) 任務(wù)控制 作者:宋寶華 e-mail:21 出處:軟件報(bào) 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, 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的參數(shù)定義如下: name:任務(wù)名; priority:任務(wù)優(yōu)先級(jí); options:任務(wù)選項(xiàng),下表給出了各種option及其含義: 選項(xiàng) 16進(jìn)制值 含義 VX_FP_TASK 00008 執(zhí)行浮點(diǎn)協(xié)處理 VX_NO_STACK_FILL 00100 不對(duì)任務(wù)堆棧填充0xee VX_PRIVATE_ENV 00080 執(zhí)行一個(gè)環(huán)境私有的任務(wù) VX_UNBREAKABLE 00002 使任務(wù)不能斷點(diǎn) VX_DSP_TASK 00200 1 = DSP協(xié)處理支持 VX_ALTIVEC_TASK 00400 1 = ALTIVEC協(xié)處理支持 stacksize:任務(wù)堆棧大小; main:任務(wù)入口函數(shù); arg1,arg10:任務(wù)入口函數(shù)參數(shù) 下面來看一個(gè)具體的例子: 例1:創(chuàng)建任務(wù) /* 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); 程序運(yùn)行,在VxSim上輸出: Hello, I am task 0 1 2 3 4 5 6 7 8 9 taskDelay(sysClkRateGet ( ) / 2)語句的含義為將任務(wù)延遲0.5S,因此,0、19的數(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ù) /* task including float calculate */ void floatTask(void) printf(%f, 100 / 30.0); /* user entry */ void user_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 int tid; /* task function */ void myFunc(void) int i; printf(Hello, I am task %dn, taskIdSelf(); /* Print task Id */ 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); /* user entry */ void user_start() printf(ready to begin a new taskn); tid = taskSpawn(myTask, 90, 0100, 2000, (FUNCPTR) myFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 這次程序僅僅輸出: Hello, I am task 0 1 2 3 4 這意味著exit(0)語句之后的循環(huán)for (i = 5; i 10; i+)沒有被執(zhí)行。 taskDelete()函數(shù):終止任務(wù)并釋放任務(wù)占用的內(nèi)存(堆棧和任務(wù)控制塊空間),其原型為:extern STATUS taskDelete (int tid); 參數(shù)tid為任務(wù)的ID。請(qǐng)看下面的例子:例4:刪除任務(wù) /* 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); /* another task function:delete my task */ void delMyTaskFunc(void) taskDelay(sysClkRateGet() *4); printf(ready to delete taskn); taskDelete(tid); /* user entry */ void user_start() printf(ready to begin new tasksn); tid = taskSpawn(myTask, 90, 0100, 2000, (FUNCPTR) myFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); taskSpawn(delMyTask, 90, 0100, 2000, (FUNCPTR)delMyTaskFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 運(yùn)行輸出: Hello, I am task 0 1 2 3 4 5 6 7 ready to begin a new task 程序?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); /* Block until semaphore available */ . . .critical region . semGive (semId);semGive (semId); /* Release semaphore */ taskUnsafe (); 5.3 延遲任務(wù) taskdelay()提供了一個(gè)簡(jiǎn)單的任務(wù)睡眠機(jī)制,常用于需要定時(shí)/延時(shí)機(jī)制的應(yīng)用中。它的原型是: STATUS taskDelay(int ticks /* number of ticks to delay task */); 可以看出使用該函數(shù)實(shí)現(xiàn)延時(shí)的單位為節(jié)拍(tick)。在VxWorks下通常以如下方式調(diào)用taskDelay()函數(shù): taskDelay(sysClkRateGet()*n); 其中的n是要延遲的時(shí)間,以秒為單位。其中的sysClkRateGet(int ticks /* number of ticks every second */)函數(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的原型為: extern STATUS taskSuspend (int tid); extern STATUS taskResume (int tid); 例5:掛起/恢復(fù)任務(wù) /* 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); /* suspend and resume task */ void suspendResumeMyTask(void) taskDelay(sysClkRateGet() *3); taskSuspend(tid); printf(my task is suspendedn); taskDelay(sysClkRateGet() *3); taskResume(tid); /* user entry */ void user_start() printf(ready to begin new tasksn); tid = taskSpawn(myTask, 90, 0100, 2000, (FUNCPTR) myFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); taskSpawn(suspendResumeMyTask, 90, 0100, 2000, (FUNCPTR) suspendResumeMyTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 運(yùn)行輸出: Hello, I am task 0 1 2 3 4 5 my task is suspended 6 7 8 9 這個(gè)程序運(yùn)行3秒后,suspendResumeMyTask任務(wù)掛起了myTask,輸出“my task is suspended”。suspendResumeMyTask本身延遲3秒后恢復(fù)myTask,使得myTask再次輸出“6 7 8 9”。顯然,“6 7 8 9”與“0 1 2 3 4 5”的輸出之間間隔了3秒以上的時(shí)間。 如果我們將上述程序改為: 例6:重啟任務(wù) /* 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); /* reset task */ void resetMyTask(void) taskDelay(sysClkRateGet() *3); printf(my task will be resetedn); taskRestart(tid); /* user entry */ void user_start() printf(ready to begin new tasksn); tid = taskSpawn(myTask, 90, 0100, 2000, (FUNCPTR) myFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); taskSpawn(resetMyTask, 90, 0100, 2000, (FUNCPTR)resetMyTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 運(yùn)行輸出: Hello, I am task 0 1 2 3 4 5 my task will be reseted Hello, I am task 0 1 2 3 4 5 6 7 8 9 我們可以使用taskRestart()函數(shù)重新啟動(dòng)一個(gè)任務(wù),不管任務(wù)當(dāng)前處于什么狀態(tài),它都會(huì)被重新開始。該API的原型是: extern STATUS taskRestart (int tid); 在例6中,程序運(yùn)行3秒后resetMyTask啟動(dòng),它復(fù)位了myTask,因此myTask被重新執(zhí)行,“Hello, I am task ”以及“0 1 2 3 4 5”被再次輸出。 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: 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 */); 請(qǐng)看例程: 例7:任務(wù)鉤子Hook /* includes */ #include vxWorks.h #include taskLib.h #include taskHookLib.h /taskHook所對(duì)應(yīng)的庫 /* task function */ void myFunc(void) int i; printf(Hello, I am task %dn, taskIdSelf(); /* Print task Id */ /* taskCreatHook */ void myTaskHook(void) printf(task hook function calledn); /* user entry */ void user_start() taskCreateHookAdd( (FUNCPTR) myTaskHook); taskSpawn(myTask, 90, 0100, 2000, (FUNCPTR) myFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 運(yùn)行輸出: task hook function called Hello, I am task 5.6 其它重要API 與任務(wù)控制相關(guān)的其它重要API還有: /設(shè)置任務(wù)優(yōu)先級(jí)extern STATUS taskOptionsSet (int tid, int mask, int newOptions); /獲得任務(wù)優(yōu)先級(jí)extern STATUS taskOptionsGet (int tid, int *pOptions); /從任務(wù)ID獲得任務(wù)名extern char *taskName (int tid); /從任務(wù)名獲得任務(wù)IDextern int taskNameToId (char *name); /確認(rèn)ID為tid的任務(wù)是否存在extern STATUS taskIdVerify (int tid); /獲得任務(wù)自身IDextern int taskIdSelf (void); /任務(wù)狀態(tài)是否為readyextern BOOL taskIsReady (int tid); /任務(wù)狀態(tài)是否為Suspendedextern BOOL taskIsSuspended (int tid); /獲得任務(wù)的TCB指針extern WIND_TCB *taskTcb (int tid); /獲得任務(wù)的優(yōu)先級(jí)STATUS taskPrioritySet (int tid, /* task ID */ int newPriority /* new priority */ ); /任務(wù)鎖定與解鎖:一個(gè)任務(wù)調(diào)用taskLock()后,任務(wù)運(yùn)行時(shí)將沒有基于優(yōu)先級(jí)的搶占發(fā)生;而taskUnlock()則用于恢復(fù)鎖定。extern STATUS taskLock (void); extern STATUS taskUnlock (void); 基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(3)任務(wù)調(diào)度03月 7th, 2006 by 宋寶華 基于嵌入式操作系統(tǒng)VxWorks的多任務(wù)并發(fā)程序設(shè)計(jì)(3) 任務(wù)調(diào)度 作者:宋寶華 e-mail:21 出處:軟件報(bào) VxWorks支持兩種方式的任務(wù)調(diào)度: (1)基于優(yōu)先級(jí)的搶占調(diào)度(Preemptive Priority Based Scheduling) 搶占是指正在執(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í)(0255)。優(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-Robin Scheduling) 時(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 /* function prototypes */ void taskOne(void); void taskTwo(void); void taskThree(void); /* globals */ #define ITER1 100 #define ITER2 10 #define PRIORITY 101 #define TIMESLICE sysClkRateGet() #define LONG_TIME 0xFFFFFFL void sched(void) /* function to create the three tasks */ int taskIdOne, taskIdTwo, taskIdThree; if (kernelTimeSlice(TIMESLICE) = OK) /* turn round-robin on */ printf(nnnntttTIMESLICE = %d secondsnnn, TIMESLICE / 60); /* spawn the three tasks */ if (taskIdOne = taskSpawn(task1, PRIORITY, 0100, 20000, (FUNCPTR)taskOne, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = ERROR) printf(taskSpawn taskOne failedn); if (taskIdTwo = taskSpawn(task2, PRIORITY, 0100, 20000, (FUNCPTR)taskTwo, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = ERROR) printf(taskSpawn taskTwo failedn); if (taskIdThree = taskSpawn(task3, PRIORITY, 0100, 20000, (FUNCPTR) taskThree, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = ERROR) printf(taskSpawn taskThree failedn); void taskOne(void) unsigned int i, j; for (i = 0; i ITER1; i+) for (j = 0; j ITER2; j+) printf(task1n); /* log messages */ for (j = 0; j LONG_TIME; j+) ; /* allow time for context switch */ void taskTwo(void) unsigned int i, j; for (i = 0; i ITER1; i+) for (j = 0; j ITER2; j+) printf(task2n); /* log messages */ for (j = 0; j LONG_TIME; j+) ; /* allow time for context switch */ void taskThree(void) unsigned int i, j; for (i = 0; i ITER1; i+) for (j = 0; j ITER2; j+) printf(task3n); /* log messages */ for (j = 0; j LONG_TIME; j+) ; /* allow time for context switch */ 程序運(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ù)原型為: STATUS kernelTimeSlice (int ticks /* time-slice in ticks or 0 to disable round-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 /* function prototypes */ void taskOne(void); void taskTwo(void); void taskThree(void); /* globals */ #define ITER1 100 #define ITER2 10 #define HIGH 100 /* high priority */ #define MID 101 /* medium priority */ #define LOW 102 /* low priority */ #define LONG_TIME 0xFFFFFFL void sched(void) /* function to create the two tasks */ int taskIdOne, taskIdTwo, taskIdThree; printf(n

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論