新聞中心

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

ucOS- II中設計了五種通訊機制

作者: 時間:2016-11-27 來源:網(wǎng)絡 收藏
在ucOS- II中設計了五種通訊機制,或者說是同步機制,分別是信號量(semaphore),互斥體(mutual exclusion semaphore),事件組(event flag),郵箱(message box)和隊列(queue),而事件(event)則是這幾種通訊機制的核心,這幾天學習了一下這幾種機制,總結一下先,呵呵。
1. 先總結一下作為核心的事件控制機制:
1.1 數(shù)據(jù)結構設計:類似于任務就緒表一樣,作者設計了等待任務表,表的作用原理和任務就緒表完全一樣,甚至共用了OSMapTbl和OSUnMapTbl這 兩個表,不用之處,任務就緒表用來查詢就緒的任務中優(yōu)先級最好的那個,而等待任務表用來查詢等待事件的任務中優(yōu)先級最高的那個,類似于就緒表,設計了兩個 變量:OSEventGrp和OSEventTbl[],不同的時候這兩個變量被設計進時間控制塊(event control block ECB)中,也就是說對于每個事件(上述五種)都有一個等待任務表。對于ECB,還有其他三個變量:OSEventType(用來標識是上述五種的哪一 種), OSEventCnt(信號量和互斥體會用到)和OSEventPtr(在郵箱中用來存放消息,在隊列中用來存放隊列塊的指針)。對于事件組來說,作者設 計了另一套數(shù)據(jù)結構,而沒有用到ECB。
1.2 事件控制的核心函數(shù)有四個,基本上就是對等待任務表的操作,這些函數(shù)將作為上述五種通訊機制的核心功能:
1.2.1OS_EventWaitListInit:初始化等待任務表, 很簡單。
1.2.2 OS_EventTaskRdy:首先找到等待該事件的優(yōu)先級最高的任務,將其從等待任務表中移走,然后更新該任務的TCB,最高根據(jù)TCB的OSTCBStat變量更新任務就緒表(如果該任務沒有等待任何事件,那么就把它加入任務就緒表)。
1.2.3 OS_EventTaskWait:首先把當前任務從任務就緒表中移走,然后把當前任務加進這個事件的等待任務表。這個函數(shù)其實就是掛起當前任務!
1.2.4 OS_EventTO:超時處理函數(shù),將當前任務從等待任務列表中移走,并更新TCB使其進入就緒狀態(tài),值得注意的是,它并不更新就緒任務表!??!
2. 信號量的實現(xiàn)
信號量的用途主要有三個:第一, 表示一個或多個事件的發(fā)生; 第二, 表示共享資源的可用(二值信號量); 第三, 表示n個相同資源的訪問(多值信號量)(這是書上的說法,我認為應該表述為: 表示共享資源對n個任務的可用)。
2.1 數(shù)據(jù)結構設計:信號量只是用到ECB,一個信號量用一個ECB表示,沒有用到其他數(shù)據(jù)結構。其中ECB的OSEventPtr變量沒有用到,只是簡單的將其設為0,因此信號量是比較簡單的一個通訊機制。
2.2 核心函數(shù)主要有四個:
2.2.1 OSSemCreate:創(chuàng)建一個信號量:首先從事件控制塊緩沖區(qū)中得到一個ECB,然后初始化這個ECB,對其中等待任務表的初始化用到OS_EventWaitListInit。
2.2.2 OSSemDel:銷毀一個信號量:有兩種情況, 第一,只有在沒有任務等待該信號量的時候才刪除;第二,不管有沒有任務等待該信號量都強制刪除;對于第一種情況,用OS_DEL_NO_PEND進行標 識,這個時候,如果確實沒有任務在等待該信號量,將ECB歸還到ECB緩沖區(qū),然后返回; 如果有任務在等待該信號量,直接返回錯誤標識,以告訴調用者刪除失敗。 對于第二種情況,用OS_DEL_ALWAYS進行標識,首先用OS_EventTaskRdy將等待任務表中的所有任務都移走,然后將該ECB歸還到 ECB緩沖區(qū)。這個時候要做判斷如果剛剛有任務在等待該信號量(這個判斷在移走之前已經(jīng)做好),就必須重新調度:OS_Sched!所以,如果當前任務不是優(yōu)先級最高的任務,那么這個函數(shù)將會被掛起,呵呵。
2.2.3 OSSemPend:該函數(shù)可能會引起當前任務被掛起:首先判斷該信號量是否可用,也就是ECB的OSEventCnt是否不為0,如果可用的話更新 ECB然后返回,任務繼續(xù)執(zhí)行;如果不可用,那么就更新當前任務的TCB,然后用OS_EventTaskWait掛起任務,然后重新調度。這時,該函數(shù) 將可能被掛起,直到當前任務獲得該信號量從而恢復執(zhí)行。然后該函數(shù)判斷當前任務繼續(xù)執(zhí)行的原因,如果是超時的話,調用OS_EventTO,如果是得到信 號量而返回的話,更新當前TCB,然后返回。另外,這也就是OS_EventTO不更新就緒表的原因——本身已經(jīng)在運行了呀,呵呵。
2.2.4 OSSemPost:該函數(shù)釋放該信號量,從而可以使正在等待該信號量的任務恢復執(zhí)行: 首先判斷等待任務表中是否有任務正在等待該信號量,如果有的話就通過OS_EventTaskRdy使等待任務表中優(yōu)先級最高的任務不再等待該信號量(具 體的操作如上面所述)。接下來(不管有沒有任務正在等待該信號量)就更新ECB,其實就是將其中的變量OSEventCnt加1。
前面對信號量 做了一個簡單的總結,下面對互斥體,郵箱和隊列以及事件組做一個總結,由于事件組沒有用到ECB,而其他的都有用到ECB,所以最后總結事件組,也就是 說,除了事件組會從一個作者專門設計的系統(tǒng)緩沖區(qū)申請用到的數(shù)據(jù)結構,其他的都會從ECB緩沖區(qū)中申請ECB。
3. 互斥體的實現(xiàn)
從其名字,mutual exclusion semaphore,可以看出來,其實互斥體屬于信號量的一種,其實它是一個二值信號量,之所以把它單獨拿出來設計,主要是為了解決任務優(yōu)先級反轉的問題 ——當該互斥體被一個任務占用的時候,如果有更高的優(yōu)先級任務等待該互斥體,那么將占用該互斥體的任務的優(yōu)先級提升到預先設定的那個比較高的優(yōu)先級,從而 能改善優(yōu)先級反轉的問題,但是不能完全去掉,呵呵。
3.1 數(shù)據(jù)結構的設計:
和信號量一樣,互斥體只用到ECB這一數(shù)據(jù)結構, 不同的是,由于它主要被設計用來解決優(yōu)先級反轉的問題,每一個互斥體都會一個實現(xiàn)設定的優(yōu)先級聯(lián)系起來,這個優(yōu)先級應該盡量比較高,這樣,擁有這個互斥體 的任務將會先被處理,從而改善優(yōu)先級反轉的問題。ECB中,OSEventType用來標識該事件對象是個互斥體;OSEventCnt的高8位用來存放 與該互斥體關聯(lián)的優(yōu)先級,而低8位存放擁有該互斥體的任務優(yōu)先級;OSEventPtr存放擁有該互斥體的任務的TCB指針;剩下的等待任務表和信號量一 樣,沒任何區(qū)別。
3.2 核心函數(shù)和信號量一樣有四個,但是由于每個互斥體都與一個任務優(yōu)先級聯(lián)系起來,實現(xiàn)有一些復雜:
3.2.1 OSMutexCreate:創(chuàng)建一個互斥體:首先判斷該優(yōu)先級有沒有被任務占用,如果有的話,創(chuàng)建失??;然后從ECB緩沖區(qū)中取一個ECB; 最后初始化得到的ECB,值得注意的是,ECB的變量OSEventCnt的高8位用來存放關聯(lián)的優(yōu)先級,當然,等待任務表還是用 OS_EventWaitListInit來初始化。
3.2.2 OSMutexDel: 刪除一個互斥體:其實現(xiàn)與信號量基本一樣,唯一的不用還是由于其關聯(lián)了一個任務優(yōu)先級,刪除的時候應該將優(yōu)先級重新標識為可用。
3.2.3 OSMutexPend:等待一個互斥體:首先判斷是否該互斥體可用,如果可用的的話就用當前任務的優(yōu)先級和TCB更新ECB,表明該互斥體已經(jīng)被當前任務占用,直接返回,這種情況最簡單; 如果互斥體已經(jīng)被其他任務占用:首先判斷占用該互斥體的任務的優(yōu)先級是不是比當前任務的優(yōu)先級低,如果是的話就要做提升占用該互斥體任務優(yōu)先級的操作,這也就是互斥體的主要用途——更新就緒任務表,更新該任務TCB,更新任務優(yōu)先級標識表OSTCBPrioTbl。剩下的處理與信號量的OSSemPend的處理完全一致:更 新當前任務的TCB,然后用OS_EventTaskWait掛起任務,然后重新調度。這時,該函數(shù)將可能被掛起,直到當前任務獲得該互斥體從而恢復執(zhí) 行。然后該函數(shù)判斷當前任務繼續(xù)執(zhí)行的原因,如果是超時的話,調用OS_EventTO,如果是得到該互斥體而返回的話,更新當前TCB,然后返回。
3.2.4 OSMutexPost:釋放一個互斥體,注意,只要占用該互斥體的任務能夠釋放該互斥體!首先檢查當前任務是否占用該互斥體,如果不是的話直接返回錯誤;然后判斷當前的任務優(yōu)先級是否被提升過,如果是的話,就做恢復當前任務的優(yōu)先級——更新就緒任務表,更新當前任務TCB,更新任務優(yōu)先級標識表OSTCBPrioTbl;接下來,通過等待任務表判斷是否有任務在等待該互斥體,如果有的話通過OS_EventTaskRdy其中優(yōu)先級最高的任務,然后將該互斥體標識為這個優(yōu)先級最高的任務所占用, 如果沒有任務在等待該互斥體,就重置它。
4. 郵箱的實現(xiàn)
郵箱(mail box)主要用來從一個任務向另外一個任務發(fā)送一個消息,其實就是一個指針,因此,與信號量和互斥提稍有不同,信號量和互斥體用來同步對資源的訪問,而這 個資源在信號量和互斥體中是沒有體現(xiàn)的,換句話說,從信號量和互斥體的ECB中不能看出是在同步哪些資源,而郵箱的話,這個資源(也就是消息)被放在 ECB中!總的說來,郵箱的實現(xiàn)相對來說很簡單!
4.1 數(shù)據(jù)機構的設計:
郵箱也只用到ECB,和信號量以及互斥體不同的是,郵箱沒有用到OSEventCnt,而是使用OSEventPtr來存放消息(指針)。其他的和信號量于互斥體相同。
4.2 核心函數(shù)也是四個,與信號量和互斥體一樣:
4.2.1 OSMboxCreate:創(chuàng)建一個郵箱:實現(xiàn)很簡單,首先申請一個ECB,然后初始化這個ECB,其中用OS_EventWaitListInit初始化等待任務表。
4.2.2 OSMboxDel:刪除一個郵箱:與信號量中OSSemDel完全相同。
4.2.3 OSMboxPend:等待一個郵箱消息:首先檢查該郵箱中是否有消息,如果有的話取出消息,然后返回; 如果郵箱中沒有消息,那么更新當前任務TCB,并用OS_EventTaskWait掛起當前任務,然后重新調度:OS_Sched! 這個時候當前任務將會被掛起,直到等待的消息來臨或者超時才得意恢復執(zhí)行,之后,它檢查郵箱中是否有消息,如果有的話,取走消息,正常返回;如果郵箱中仍 然沒有消息,那么當前任務恢復執(zhí)行是因為超時,于是返回超時錯誤!
上一頁 1 2 下一頁

關鍵詞: ucOS-I通訊機

評論


相關推薦

技術專區(qū)

關閉