新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ucOS- II中設(shè)計(jì)了五種通訊機(jī)制

ucOS- II中設(shè)計(jì)了五種通訊機(jī)制

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

上一頁 1 2 下一頁

關(guān)鍵詞: ucOS-I通訊機(jī)

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉