事件控制塊的初始化代碼應在操作系統初始化函數OS_Init中被調用,實際上也是如此。
50.png (38.82 KB, 下載次數: 55)
下載附件
2013-8-1 16:17 上傳
事件控制塊的初始化函數是OS_InitEventList,在內核代碼os_core.c中。該代碼如下所示:
51.png (42.83 KB, 下載次數: 59)
下載附件
2013-8-1 16:17 上傳
可見,ECB初始化函數OS_InitEventList首先清空了所有的ECB,也就是清空了事件表。然后從0到(OS_MAX_EVENTS-1u)循環對除最后一個ECB之外的所有ECB進行初始化,并順便構建了單項的鏈表。循環結束后最后一個ECB的OSEventTbl[OS_MAX_EVENTS-1]的OSEventPtr域指向空地址0,構建完成了空閑事件鏈表,然后將ECB空閑鏈表的表頭地址給OSEventFreeList,初始化完成。
當建立一個事件或消息(如信號量、郵箱、消息隊列)時,如信號量的建立函數OSSemCreate等,需要對事件等代表進行初始化。因為雖然事件等待表在操作系統初始化時調用OS_InitEventList已經被初始化了,但很可能在操作系統的運行過程中被使用過,因此不能保證是被清零的。事件等待表初始化函數實現對指定事件控制塊中事件等待表和事件等待組清零,可被操作系統的其他函數調用。
事件等待表初始化函數為OS_EventWaitListInit,代碼在內核os_core.c中,參數是ECB的地址,程序如下所示:
52.png (11.05 KB, 下載次數: 56)
下載附件
2013-8-1 16:17 上傳
可見,事件等代表初始化函數為OS_EventWaitListInit所做的工作就是對指定ECB清空任務等待組和任務等待表。
當任務等待事件發生,并獲得ECB后,需要在ECB中標記任務在等待事件的發生,才可以在事件發生時取消任務的阻塞。將任務在ECB中進行登記的函數是OS_EventTaskWait,參數是事件控制塊的指針。與OS_EventWaitListInit類似,OS_EventTaskWait在任務調用信號量、郵箱等事件等待函數時被對應的函數調用。因為任務的優先級可以通過當前的TCB指針OSTCBCur得到,因此沒有作為參數傳遞。
設置事件等待的函數OS_EventTaskWait的代碼如下所示:
53.png (20.69 KB, 下載次數: 74)
下載附件
2013-8-1 16:17 上傳
由代碼的分析可見,事件等待的函數OS_EventTaskWait只做以下兩件事情:
(1)標記。在ECB中登記本任務,即在ECB的事件等待表中對應優先級處標記為1,事件等待組中對應位標記為1.
(2)取消標記。在就緒表和就緒組中取消對該事件的就緒的標記,將就緒表中對應優先級處標記為0,如果就緒表中該任務所在的一組沒有任務就緒,將就緒組中的對應位標記為0。
OS_EventTaskRemove是與OS_EventTaskWait相反的操作,當一個事件由于某種原因不再需要等待事件(如任務被刪除)時,就需要在該事件的等待表中取消該事件的等待標志,否則會引起嚴重的后果,例如,去運行一個已經被刪除的任務。事件等待組中的一位表示事件等待表中一行8個任務是否有任務在等待事件,因此只是一個任務不再等待不一定要刪除事件等待組中的對應標志,需要進行判斷。OS_EventTaskRemove的代碼如下所示:
54.png (14.25 KB, 下載次數: 38)
下載附件
2013-8-1 16:17 上傳
由代碼可知,OS_EventTaskRemove執行了一項操作,就是取消事件等待表和事件等待組中的任務等待標志。
任務因為等待事件而在ECB中登記自己的等待,當時間發生時,如果該任務是事件等待表中優先級最高的任務,任務唄取消等待而回到就緒態。等待的事件發生的函數為OS_EventTaskRdy,從函數名來看,含義為將等待事件的任務就緒。該函數的聲明如下所示:
55.png (36.07 KB, 下載次數: 46)
下載附件
2013-8-1 16:17 上傳
56.png (35.41 KB, 下載次數: 56)
下載附件
2013-8-1 16:17 上傳
參數解析如下:
(^_^) prevent:對應的ECB指針
(^_^) pmsg:消息指針。當使用諸如消息隊列或消息郵箱的消息服務的時候使用該指針。當是信號量或其他事件的時候不使用該指針。
(^_^) msk:清除狀態位的掩碼。例如,使用OSSemPost()提交信號量時OS_STAT_SEM,使用OSMboxPost()提交消息的時候使用OS_STAT_MBOX,以清除TCB中的對應狀態位。使用該參數的目的是不需要操作系統判定是何種事件發生而增加運行成本。
(^_^) pend_stat:表示等待(pend) 結束,任務就緒的原因,可以是下面的值:
》》》 OS_STAT_PEND_OK:任務就緒的原因是等待正常結束,諸如事件發生、超時。
》》》 OS_STAT_PEND_ABORT:因為異常。
返回值:任務優先級。
總結一下,OS_EventTaskRdy的流程如下:
(1) 在事件等待表和事件等待組中找到最高優先級的等待任務的優先級。
(2) 根據優先級查任務優先級指針表,找到該任務的TCB指針。
(3) 對任務控制塊的相關參數進行賦值。
(4) 判斷任務是否被掛起,如果未被掛起就將任務就緒。完成從阻塞態到就緒態的轉換。
(5) 調用OS_EventTaskRemove在ECB的事件等待表中刪除該任務。
(6) 返回任務的優先級。
|