ucOS- II中設(shè)計了五種通訊機制
4.2.4 OSMboxPost:往郵箱發(fā)送消息: 首先檢查是否有任務(wù)正在等待郵箱消息的到來,如果有的話就通過OS_EventTaskRdy找到優(yōu)先級最高的任務(wù),然后重新調(diào)度,注意,這時候要發(fā)送的消息會放到優(yōu)先級最高任務(wù)的TCB中!如果沒有任務(wù)在等待該郵箱消息的到來,就直接把消息放到郵箱中。
5 隊列的實現(xiàn)
隊列的實現(xiàn)類似于郵箱,也是用來從一個任務(wù)向其他任務(wù)發(fā)送消息,不過,隊列更為復(fù)雜,之所以稱之為隊列,它可以發(fā)送多個消息,可以把郵箱看成是只發(fā)送一個消息的隊列。
5.1 數(shù)據(jù)結(jié)構(gòu)的設(shè)計:
由于隊列可以發(fā)送多個消息,所以僅僅用ECB不能滿足要求,于是作者引入了另外一個數(shù)據(jù)結(jié)構(gòu)QS_Q,用來描述隊列代表的多個消息,但是這里與 郵箱不同的是,QS_Q本身并不包含消息本身,而是隊列代表的一系列消息的描述。當(dāng)然,真正的消息放在一個系統(tǒng)的消息緩沖區(qū)MsgTbl,這個緩沖區(qū)是預(yù) 先定義好的,其大小根據(jù)實際的應(yīng)用而定制。所以對于隊列來說,用到三個數(shù)據(jù)結(jié)構(gòu),ECB, QS_Q, MsgTbl,其中ECB和QS_Q是每個隊列都有一個,而MsgTbl是系統(tǒng)中所有隊列共享的!
QS_Q由ECB的變量OSEventPtr引出,ECB的OSEventCnt沒有用到,其他的變量用法同信號量。對于QS_Q來說,和ECB一樣是從系統(tǒng)QS_Q緩沖區(qū)中申請的。
5.2 核心函數(shù)為五個,其中四個類似于前面的信號量,互斥體和郵箱,此外還多了一個清空隊列的函數(shù):
5.2.1 OSQCreate:創(chuàng)建一個隊列:首先申請一個ECB,然后申請一個QS_Q,最后初始化申請到的ECB和QS_Q,其中用到OS_EventWaitListInit初始化等待任務(wù)表。
5.2.2 OSQDel:刪除一個隊列:實現(xiàn)和信號量的OSSemDel基本一樣,不同的是,由于隊列引入了QS_Q,必須加歸還申請到的QS_Q到系統(tǒng)QS_Q緩沖區(qū)的操作。
5.2.3 OSQPend:等待一個消息:注意這個函數(shù)只是等待一個消息,而這個消息是不是想要的它并不知道!首 先通過QS_Q判斷該隊列是不是有消息,如果有的話更新QS_Q然后返回;如果該隊列沒有消息,那么更新當(dāng)前任務(wù)的TCB以表明當(dāng)前任務(wù)正在等待該隊列的 消息,然后通過OS_EventTaskWait掛起當(dāng)前任務(wù),然后重新調(diào)度——OS_Sched!這個時候當(dāng)前任務(wù)會等到消息到來或者超時才會得以繼續(xù) 執(zhí)行。。。當(dāng)繼續(xù)執(zhí)行的時候,判斷是得到消息才執(zhí)行,還是超時,如果是前者的話,直接更新當(dāng)前任務(wù)的TCB;如果是后者的話,通過OS_EventTO更 新狀態(tài)。
5.2.4 OSQPost:發(fā)送一個消息:這個函數(shù)放一個消息到隊列。首先檢查是不是有任務(wù)在等待該隊列的消息,如果有的話,就通過OS_EventTaskRdy 找到正在等待該隊列消息的任務(wù)中優(yōu)先級最高的那個,然后重新調(diào)度——OS_Sched!如果沒有的話,更新該隊列的QS_Q,也就是加一個消息進該隊列。
5.2.5 OSQFlush:刷新該隊列,其實就是簡單的重置QS_Q,系統(tǒng)消息緩沖區(qū)MsgTbl是不需要改動的!
前面對信號量,互斥體,郵箱,隊列做了一個簡單的總結(jié),這四個通訊機制的核心都是ECB,而這里總結(jié)的事件組(evnet flag),作者沒有用ECB,而是重新設(shè)計了兩個單獨的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)。下面對事件組這最復(fù)雜的通訊機制做一總結(jié),呵呵
6 事件組
事件組的用途主要是把多個事件和多個任務(wù)能夠聯(lián)系起來,使通訊機制更加靈活,它有兩部分組成:一是表示了各個事件的狀態(tài);二是等待這些事件的任務(wù)列表。
6.1 數(shù)據(jù)結(jié)構(gòu)設(shè)計:
如上面提到的,事件組用到了全新的兩個數(shù)據(jù)結(jié)構(gòu):OS_FLAG_GRP和OS_FLAG_NODE——OS_FLAG_GRP有三個變 量:OSFlagType(和ECB中的OSEventType一樣,用來標(biāo)識這是一個事件組),OSFlagWaitList(負責(zé)引出等待事件組的任 務(wù)列表)和OSFlagFlags(標(biāo)識當(dāng)前事件狀態(tài));OS_FLAG_NODE有六個變量:OSFlagNodeNext和 OSFlagNodePrev(用來將OS_FLAG_NODE構(gòu)成雙向列表),OSFlagNodeTCB(正在等待事件組的任務(wù) TCB),OSFlagNodeFlagGrp(該變量反向指到OS_FLAG_GRP,用來記錄事件組),OSFlagNodeFlags(標(biāo)識任務(wù)和 該節(jié)點關(guān)聯(lián)的任務(wù)正在等待的事件標(biāo)志)和OSFlagNodeWaitType(標(biāo)識該節(jié)點相關(guān)聯(lián)任務(wù)正在等待的方式:是全部等到,還是只等其中一個)。 從上面不難看出,OS_FLAG_GRP其實相當(dāng)于ECB中的除了等待任務(wù)表的其他三個變量,而OS_FLAG_NODE相當(dāng)于等待任務(wù)表,不同的是,由 于等待的任務(wù)不是僅僅等待一個事件,而是等待一系列事件,這樣,等待任務(wù)表就不能勝任了——因為等待任務(wù)表只能標(biāo)明哪些個任務(wù)正在等待,但是等待的目標(biāo)是 唯一的,而這里等待的目標(biāo)可能會是多個!
6.2 核心功能函數(shù):
由于用到了不同的數(shù)據(jù)結(jié)構(gòu),OS_EventWaitListInit,OS_EventTaskRdy,OS_EventTaskWait和 OS_EventTO就必須重新設(shè)計,作者在這里設(shè)計了另外的核心功能函數(shù),OS_FlagBlock,OS_FlagRdy和 OS_FlagUnlink。
6.2.1 OS_FlagBlock:其作用相當(dāng)于OS_EventTaskWait:將當(dāng)前任務(wù)從就緒任務(wù)表中移走,更新當(dāng)前任務(wù)的TCB,不同的是,在 OS_EventTaskWait中將當(dāng)前任務(wù)加入等待任務(wù)表,而這里由于沒有用到等待任務(wù)表,而是創(chuàng)建一個OS_FLAG_NODE,換句話說,只要有 OS_FLAG_NODE就表明有任務(wù)在等待事件組,其實原理上和等待任務(wù)表是一樣的。
6.2.2 OS_FlagRdy:其作用相當(dāng)于OS_FlagTaskRdy:將OS_FLAG_NODE所指向的任務(wù)的TCB更新以表明等到了事件組,如果該任務(wù) 不在等待其他的目標(biāo),將其加入就緒任務(wù)表中。然后用OS_FlagUnlink將此任務(wù)的OS_FLAG_NODE刪除。
6.2.3 OS_FlagUnlink:該函數(shù)主要是把特定的OS_FLAG_NODE從等待任務(wù)列表中刪除。
6.3 核心函數(shù)和信號量類似,有四個,其實現(xiàn)比較簡單:
6.3.1 OSFlagCreate: 創(chuàng)建一個事件組:從系統(tǒng)事件組緩沖區(qū)中申請一個OS_FLAG_GRP,然后初始化該OS_FLAG_GRP。
6.3.2 OSFlagDel:刪除一個事件組:和信號量的OSSemDel幾乎完全一樣,不同的是用OS_FlagRdy而不是OS_EventTaskRdy。
6.3.3 OSFlagPend:等待一個事件組:這里的等待有兩種情況:等待所有的事件到來,等待任何一個事件到來。不管哪種情況,都是先判斷需要的標(biāo)識是不是已 經(jīng)到來,如果到來的話就更新事件組,然后返回;如果沒有到來的話,就會用OS_FlagBlock為當(dāng)前任務(wù)產(chǎn)生一個OS_FLAG_NODE,并將其加 進雙向鏈表里。
6.3.4 OSFlagPost:標(biāo)識一個事件組一些標(biāo)識已經(jīng)到來:先更新OS_FLAG_GRP,然后遍歷OS_FLAG_NODE的雙向鏈表,用OS_FlagRdy使那些正在等待這些標(biāo)識的任務(wù)不再等待。
7 各種通訊機制的比較
綜合以上五種通訊機制可以看出:信號量是最普通的通訊機制,當(dāng)需要一般的同步或者資源保護的話,用信號量就可以了;互斥體主要用來解決優(yōu)先級反 轉(zhuǎn)的問題,當(dāng)需要在任務(wù)間同步資源的時候,用互斥體;郵箱主要用來將一個消息從一個任務(wù)發(fā)送到另一個任務(wù);隊列可以看作是擴展的郵箱,隊列可以發(fā)送多個消 息;事件組是最復(fù)雜的一個通許機制,但最靈活,可以在任務(wù)間用多個事件標(biāo)識來同步,因此用起來需要特別注意!
關(guān)鍵詞:
ucOS-I通訊機
相關(guān)推薦
-
-
技創(chuàng)快刀 | 2004-04-29
-
wsser | 2004-07-25
-
Gao | 2003-02-17
-
-
-
-
jameszxj | 2003-09-06
-
唐朝 | 2003-07-11
-
-
-
評論