ucos

 重入與不可重入:

可重入函數指當一個函數在被調用時,同時還能被其他函數調用,且不會產生錯誤.
不可重入函數則不能同時被多次調用,多次調用可能會產生錯誤.

例子:某函數有一個變量爲全局變量,則如果該函數有多個實例在交替運行的話,由於同時存取
同一全局變量,導致該變量被不同實例改變而引起錯誤.

信號量:
與同一共享數據打交道(可能是全局變量,也可能是共享資源如UART,打印機等)的任務調用等待
信號量函數OSSemPend(),處理完後調用釋放信號量函數OSSemPost().
爲防止無限等待可設置等待超時.

例子:
//任務Task要存取共享數據,如果該數據正在被其他任務使用,則任務Task只能等待別的任務用
//完,然後分配給任務Task使用.用完後釋放該信號量,以供給其他任務使用(或者說將資源歸還
//給操作系統).
void Task(void)
{
    OSSemPend(...);
    perform operation;    //porcess the data
    OSSemPost(...);
}

信號量也可能是隱藏的.如多任務共享UART時,信號量可隱藏在驅動函數中.

信號量操作:
初始化/建立 INITILIZE/CREATE
等待信號/掛起 WAIT/PEND
給信號 SIGNAL/POST

信號量類型:
二進制    0/1
計數型    0 ~ 2^width - 1
如果某種資源只有1個,可用二進制型信號量,如RS232接口.
如果資源有多個,可用計數型信號量,如系統緩衝區一般有多個.

死鎖:
兩個任務無限期相互等待對方控制的資源.可用信號量等待超時來化解.

事件標誌(Event Flag)
用於任務與多個事件同步.
可用多個事件的組合發信號給多個任務.
可將8/16/32個事件標誌組合在一起,當任務所需的事件都發生了,任務結束掛起,繼續運行


任務間通訊(Intertask Communication)
兩個途徑:
1.通過全局變量.與中斷函數進行通訊只能通過全局變量.
2.發送消息給另一個任務.

發送消息的方式有郵箱(Mail Box)和消息隊列(Message Queue)

郵箱(Mail Box)
一個任務通過內核服務給另一個任務發消息.
內核提供的郵箱服務:
郵箱內消息內容初始化;
將消息放入郵箱(POST);
等待有消息進入郵箱(PEND);

例子:
TASK1 --(POST)--> MAIL BOX --(PEND)--> TASK2

可在主程序中創建郵箱,則在任務中就可直接使用.
疑問:也可在任務中創建郵箱,但此時,郵箱能否接收其他任務發送消息?能否發送消息給其他任務?

消息隊列(Message Queue)
實際上是郵箱陣列.
任務或ISR可將消息放入消息隊列(POST),一個或多個任務可從消息隊列中得到消息.
傳遞的消息實際上是傳遞的指針指向的內容.消息隊列的進出通常有規則,如FIFO.

例子:
ISR --(POST)--> MSG QUEUE --(PEND)--> TASK

疑問:消息隊列屬於某個任務?還是所有任務公用的?任務能從消息隊列中取得消息,
並執行相應的操作.任務也可以向外發送消息,但是是否應該指明發送的消息是送給誰的?
在Windows系統的應用程序中,程序的運行是基於事件驅動,消息循環的.每個應用程序進程
都有自己的消息隊列.如一個進程1發送消息給進程2,進程2收到消息便繼續往下執行,否則
就掛起什麼都不幹.也即是沒有事件的驅動,程序是不往下運行的.程序的運行就是依靠不
斷的消息循環來進行下去,程序從消息隊列中接收自己的消息,而發送消息時需指明將消息
送給哪個進程.

某一個進程發送一條消息,指明瞭需要送給哪個進程,該消息進入系統的消息隊列,系統將
該則消息投遞到目的進程的消息緩存中.而接收消息的進程則讀取消息並處理消息.
在這個過程中,系統就像一個郵局,進程發送消息就像寄信,系統投遞消息就像郵遞員送信.

在uC/OS中,可以創建一個消息隊列,並返回一個該消息隊列的標識,用戶任務就可以通過
這個標識向隊列中發送消息或接收消息,這樣看來不在發送消息時指定接收消息的任務是
可以的.但當任務較多,且創建了較多的消息隊列後,多個任務使用消息隊列時是否會產生
誤發送或誤接收等問題.對於uC/OS中的其他類型資源如Mail Box也是如此.


用戶應用uC/OS系統的框架:

main()
{
    ...
    OSInit();
    ...
    OSTaskCreate();
    ...
    OSStart();
}

OSInit()會進行一些初始化,包括Mail Box,Queue,Memory Partition等的初始化.
並創建OS_Idle_Task.

OSTaskCreate()用來創建用戶任務,uC/OS應該也支持動態創建任務,即在用戶任務中來
創建其他任務,並可將其刪除.不過uC/OS稱任務被刪除後,代碼仍在,只是不再調度該任
務.而Linux則是將任務從內存中釋放.這可能與CPU有關.如果是哈佛結構的(如51單片
機),代碼是存放在ROM中的,無法刪除,一般對於嵌入式系統而言,多數都是屬於哈佛結
構的CPU吧.而PC機的CPU是普林斯頓結構,程序代碼和數據都是存放於內存中的,當一個
任務不再運行了,就可釋放其佔據的內存空間,以供其他程序使用.

OSStart()開始進行調度.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章