1. 程式人生 > >UC/OS II 訊息佇列

UC/OS II 訊息佇列

訊息郵箱只能儲存一條訊息,訊息佇列沒有這一侷限,可以容納多條資訊佇列,按照先進先出(FIFO)的原則傳送和接受訊息。 訊息佇列的實體不是作業系統提供的,而是由使用者任務提供的。作業系統提供的是對其進行管理的程式。 1:訊息佇列的資料結構 訊息佇列的資料結構主要包括訊息佇列、訊息佇列控制塊(QCB)、訊息佇列控制塊陣列、空閒連結串列、事件控制塊(ECB)等。 訊息佇列的資料結構定義為一個指標陣列,定義格式為void *MessQ[SIZE],SIZE是訊息佇列裡訊息的數量,指標陣列的每個成員都是指標,指向訊息實體的地址。 訊息佇列控制塊(QCB)是訊息佇列管理的核心資料結構。每個QCB管理一個訊息佇列,是訊息佇列實體存在的唯一依據。 typedef struct os_q {                        struct os_q   *OSQPtr;              //指向下一個QCB,主要是用於空閒QCB連結串列的時候     void         **OSQStart;            //指向訊息佇列的首地址     void         **OSQEnd;              //指向訊息佇列的尾地址     void         **OSQIn;               //插入訊息的地址     void         **OSQOut;              //取訊息的地址     INT16U         OSQSize;             //佇列的最大容量     INT16U         OSQEntries;          //佇列中當前的容量 } OS_Q QCB的實體在UCOSii.h中定義  OS_EXT  OS_Q              OSQTbl[OS_MAX_QS];   OS_MAX_QS系統預設為4  我們可以根據自己的需求進行重新配置 QCB沒有被使用會連線在在一個單向連結串列,OSQWaitList指標指向該連結串列表頭。 2:訊息佇列的管理
2.1:訊息佇列的初始化OS_QInit 我們若使用訊息佇列,系統初始化函式OS_Init會在進行系統初始化的時候,會呼叫OS_QInit函式對訊息佇列控制塊進行初始化。 OS_QInit的主要功能跟訊號量的初始化很類似。 這裡就是將OS_Q              OSQTbl[OS_MAX_QS]中的陣列成員進行初始化設定,同時將這些QCB連線成一個單鏈表,並且OSQWaitList指標指向該連結串列表頭。 2.2:建立訊息佇列OSQCreate OSQCreate的功能為從空閒QCB中取出一個QCB進行設定,返回ECB的地址 函式原型OS_EVENT  *OSQCreate (void    **start,INT16U    size)  start是使用者定義的訊息佇列指標陣列的地址的首地址。 其主要程式碼如下: if (pevent != (OS_EVENT *)0) {               //空閒ECB連結串列中是否為空         OS_ENTER_CRITICAL();         pq = OSQFreeList;                        //取QCB空閒連結串列表頭地址         if (pq != (OS_Q *)0) {                   //QCB空閒鏈是否為空             OSQFreeList            = OSQFreeList->OSQPtr; //去QCB空閒連結串列的第一個QCB             OS_EXIT_CRITICAL();   //初始化QCB             pq->OSQStart           = start;                            pq->OSQEnd             = &start[size];
            pq->OSQIn              = start;
            pq->OSQOut             = start;
            pq->OSQSize            = size;             pq->OSQEntries         = 0u; //初始化ECB             pevent->OSEventType    = OS_EVENT_TYPE_Q;
            pevent->OSEventCnt     = 0u;
            pevent->OSEventPtr     = pq;
#if OS_EVENT_NAME_EN > 0u
            pevent->OSEventName    = (INT8U *)(void *)"?"; #endif             OS_EventWaitListInit(pevent);                 //初始化事件控制塊的等任務待陣列和表         } else {             pevent->OSEventPtr = (void *)OSEventFreeList; //ECB空閒連結串列為空,沒有空閒的QCB             OSEventFreeList    = pevent;
            OS_EXIT_CRITICAL();
            pevent = (OS_EVENT *)0;  //pevent為空
        }     } 2.3:刪除訊息佇列OSQDel
刪除訊息佇列與刪除訊號量差不多,對ECB的操作是一樣的,但是訊息佇列多了一個QCB的處理。 對QCB處理的程式碼如下: //下面就是將相關的QCB放到QCB空閒連結串列中   pq                     = (OS_Q *)pevent->OSEventPtr;     pq->OSQPtr             = OSQFreeList;   OSQFreeList            = pq; 2.4:訊息佇列重新整理OSQFlush 該函式的功能就是重新整理訊息佇列,清空訊息佇列。 其原始碼如下,將佇列的隊頭和隊尾都指向訊息佇列的基地址。 pq             = (OS_Q *)pevent->OSEventPtr;   pq->OSQIn      = pq->OSQStart; pq->OSQOut     = pq->OSQStart; 2.5申請訊息佇列中的訊息OSQPend
該函式的功能是任務向訊息佇列申請訊息,若是訊息佇列中有訊息則取訊息,若是沒有訊息,則取阻塞等待。 該函式的原型如下:void  *OSQPend (OS_EVENT  *pevent, INT32U     timeout,  INT8U     *perr) 函式的功能實現和訊息郵箱差不多。只是在判斷是否有訊息上有點區別,如下原始碼: pq = (OS_Q *)pevent->OSEventPtr;             //QCB的地址     if (pq->OSQEntries > 0u) {                   //判斷訊息佇列是否為空         pmsg = *pq->OSQOut++;                    //取佇列中的訊息         pq->OSQEntries--;                        //訊息佇列訊息數目減1         if (pq->OSQOut == pq->OSQEnd) { //去訊息的地址在佇列的尾地址             pq->OSQOut = pq->OSQStart; //去訊息的地址賦值為佇列的首地址(迴圈佇列)         }
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;           return (pmsg);                           //返回訊息地址     } //若是為空,就阻塞任務。事件阻塞任務的方式除了事件標誌組有點不一樣之外,其他的事件得不到滿足阻塞任務的方式都是一樣的。 需要注意的是阻塞後重新就緒,任務不回在QCB中取訊息,而是通過任務控制塊中的OSTCBMsg 成員獲取訊息。 因為會阻塞,所以回覆就緒後,取佇列中第一個訊息。所以可以用OSTCBMsg。 對照後面訊息傳送,若是在提交訊息的時候,沒有阻塞,就會放到佇列中,有阻塞,喚醒阻塞任務,訊息地址存入喚醒人的任務控制快的OSTCBMsg 2.6放棄訊息等待函式OSQPendAbort 該函式的主要功能為喚醒所有等待的訊息而阻塞的任務。該函式只能由非等待阻塞的任務執行,等待訊息阻塞的任務是不可能去執行該函式的。 該函式的原型為:INT8U  OSQPendAbort (OS_EVENT  *pevent, INT8U      opt,  INT8U     *perr) opt選項,兩種情況 OS_POST_OPT_NONE         放棄等待,然後喚醒等待任務中的最高優先順序的任務,就是執行OSMboxPost函式一樣的功能 OS_POST_OPT_BROADCAST    放棄等待廣播給所有的等待任務,喚醒所有等待任務 2.7傳送訊息到訊息佇列中OSQPost 該函式的原型為INT8U  OSQPost (OS_EVENT  *pevent, void      *pmsg) 該函式的主要功能為向佇列傳送一個訊息,若是有任務在等待佇列訊息,喚醒任務,重新排程,如果沒有,則更新訊息佇列。 其主要程式碼如下: if (pevent->OSEventGrp != 0u) {                    //是否有任務在等待佇列中的訊息                                                        //喚醒最等待訊息的最高優先順序任務,並且將訊息地址賦給阻塞最高優先順序任務控制快的OSTCBMsg         (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);         OS_EXIT_CRITICAL();         OS_Sched();                                    //執行排程,執行就緒最高優先的任務         return (OS_ERR_NONE);
    }     pq = (OS_Q *)pevent->OSEventPtr;                   //     if (pq->OSQEntries >= pq->OSQSize) {               //如果訊息數目大於訊息佇列容量即佇列已滿,立即返回,不操作佇列         OS_EXIT_CRITICAL();
        return (OS_ERR_Q_FULL);     }     *pq->OSQIn++ = pmsg;                               //佇列沒滿,訊息插入佇列中     pq->OSQEntries++;                                  //佇列訊息數目加一     if (pq->OSQIn == pq->OSQEnd) {                     //如果插入訊息位置在佇列的尾地址,則將插入位置移到佇列的頭地址         pq->OSQIn = pq->OSQStart;     } 2.8:傳送訊息到訊息佇列中OSQPostFront 該函式跟2.7中的函式最大的不同就是,提交訊息插入的位置不是佇列的尾部,而是佇列的頭部。這個就不像是佇列的操作,而是有點像堆疊的操作。 2.9:單選項的訊息傳送OSQPostOpt 函式的原型為INT8U  OSQPostOpt (OS_EVENT  *pevent, void      *pmsg, INT8U      opt) 跟2.8 2.9不同的是,這個函式引數中有一個opt引數。 該引數有四種情況: OS_POST_OPT_NONE          訊息傳送,而且喚醒單個等待任務 OS_POST_OPT_BROADCAST    訊息廣播發送,喚醒所有等待任務 OS_POST_OPT_FRONT        傳送將訊息,並且其插入到佇列的頭部。類似於2.8的功能 OS_POST_OPT_NO_SCHED    訊息提交之後,但是並不執行任務排程。 2.10:不等待請求訊息佇列函式OSQAccept 函式的原型為void  *OSQAccept (OS_EVENT  *pevent, INT8U     *perr) 該函式功能為向佇列請求訊息,若有訊息,則返回非空指標。若是沒有訊息,不等待,返回空指標,轉而執行其他部分。 2.11查詢訊息佇列的狀態OSQQuery

相關推薦

uC/OS-II訊息佇列及操作

使用訊息佇列可在任務之間傳遞多條訊息,訊息佇列由三部分組成:事件控制塊、訊息佇列和訊息。 事件控制元件塊成員OSEventPtr指向一個叫做佇列控制塊(OS_Q)的結構,該結構管理著一個數組MsgTb1[],該陣列中的元素都是指向訊息的指標。一. 訊息佇列的操作 1. 建立

uc/os-ii訊息佇列

使用訊息佇列可以在任務之間傳遞多條訊息。訊息佇列由三個部分組成:事件控制塊、訊息佇列和訊息。 訊息佇列的資料結構如下圖所示。從圖中可以看到,訊息佇列相當於一個共用一個任務等待列表的訊息郵箱陣列,事件控制塊成員OSEventPtr指向了一個叫做佇列控制塊(OS_

UC/OS II 訊息佇列

訊息郵箱只能儲存一條訊息,訊息佇列沒有這一侷限,可以容納多條資訊佇列,按照先進先出(FIFO)的原則傳送和接受訊息。 訊息佇列的實體不是作業系統提供的,而是由使用者任務提供的。作業系統提供的是對其進行管理的程式。 1:訊息佇列的資料結構 訊息佇列的資料結構主要包括訊息佇列、

uC/OS訊息佇列——uC/OS學習筆記(七)

1.訊息佇列的介紹     使用訊息佇列可在任務之間傳遞多條訊息。訊息佇列相當於訊息郵箱集合,一個郵箱只能在任務間傳遞一條訊息,而訊息佇列則可以傳遞多條訊息。訊息佇列由三部分組成:事件控制塊、訊息佇列和訊息。 2.訊息佇列的操作    a)建立訊息佇列:QSQCreate

uc/os-ii訊息郵箱

訊息郵箱是一種通訊機制,它能使任務或中斷服務向另一個任務傳送一個指標型的變數,這個指標指向一個包含指定“訊息”的資料結構。訊息郵箱傳送的不是訊息本身,而是訊息的地址指標。使用訊息郵箱之前,必須先建立訊息郵箱,並且要指定指標的初始值。一般情況下,這個初始值是NUL

uC/OS-II 學習筆記之:訊息佇列

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

uC/OS-II 最簡單的訊息佇列

 #define MESSAGES_MAX_SIZE 1000   /*訊息佇列緩衝區的大小*/ void  *MsgGrp[MESSAGES_MAX_SIZE];     /*訊息陣列,訊息陣列存放著各訊息的指標*/  OS_EVENT *StrQueue;     

UC/OS-II學習筆記之訊息佇列使用

對訊息佇列的學習理解有點難,對技術來說,一本好的書一般是原理和例子相結合的,可惜我找到的很少。書上說訊息佇列實際上是多個郵箱組成的陣列,是一個列表。這個陣列其實是個指標陣列,裡面每個指標可以指向不同型別的變數,通過傳遞一個個指標,我們可以做到傳遞指標所指向的一個個變數。(順便複習下,一個郵箱只能傳遞一個指標,

uC/OS-II 學習筆記:訊息佇列

二、訊息佇列的操作函式: (1)建立訊息佇列函式:OS_EVENT OSQCreate(void **start, INT16U size) (2)請求訊息佇列函式:void *OSQPend(OS_EVENT *pEvent, INI16U timeout, INT8U *err) (3)向訊息佇列傳送訊息

uC/OS-II學習筆記 訊息佇列

對訊息佇列的學習理解有點難,對技術來說,一本好的書一般是原理和例子相結合的,可惜我找到的很少。書上說訊息佇列實際上是多個郵箱組成的陣列,是一個列表。這個陣列其實是個指標陣列,裡面每個指標可以指向不同型別的變數,通過傳遞一個個指標,我們可以做到傳遞指標所指向的一個個變數。(順便

uC/OS-II 學習筆記之:訊息郵箱

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

uc/os-ii任務排程的鎖定與解鎖

排程器上鎖函式OSSchedlock()的功能是用於禁止任務排程,使任務保持對CPU的控制權。排程器開鎖函式OSSchedUnlock()的功能是解除對任務排程的禁止。 排程器上鎖和開鎖的實現原理是:對全域性變數鎖定巢狀計數器OSLockNesting進行操作

uC/OS訊息郵箱使用經驗

uC/OS下任務之間通訊的方式之一有訊息郵箱,使用訊息郵箱有兩種方式: (1)資料的存放 (2)傳遞指向一個數據的指標,就是傳遞多個數據。  經驗小結如下: 一、資料存放,存放單個數據 郵箱可以傳遞任

嵌入式實時作業系統uc/os-ii 原理及應用 讀書筆記

對任務就緒表的操作理解: 將優先級別為prio的任務置為就緒狀態,可使用如下程式碼 OSRdyGrp |= OSMapTbl[prio >>3];//將prio任務所在的組狀態置為1,表示該組有任務就緒。 OSRdyTbl[prio>>3] |= O

uC/OS-II任務排程中判斷最高優先順序

一、任務優先順序的表示    uC/OS-II中,規定最多可以有64個任務。每個任務的優先順序不能相同,因此,優先順序為0~63.數字越小,優先順序越高,那麼0就是最高優先順序,63就是最低優先順序。系統保留了優先順序最高及最低的各4個,因此使用者不能使用這8個優先順序作為自己的任務的優先順序。巨集OS_L

uC/OS-II核心架構解析---uC/OS-II通訊與同步

1. 訊息郵箱Mbox       Mbox用於多工間單一訊息的傳遞,uC/OS-II使用ECB管理Mbox的基本資訊,OSEventPtr指向建立Mbox時指定的記憶體空間。事件的建立由具體的事件管理程式實現。主要包含在C原始檔OS_MBOX.C中。 OS_EVENT

UC/OS-II功能介紹、要點記錄

可見總用時位各過程的總和,我們可以想象得出這樣的做法是很浪費時間的,我們任何人都不會這麼去做,採用UC/OS-II多工管理思想則可以將此事務按照另一種方式完成,如圖Pic1.2中的多執行緒方式,由圖比較可以看出,整個事務在t5時刻完成,當菜炒好時飯也做好不久,這樣的方法使總用時減少了,分析原因,可以知道是我們

UC/OS-II 任務的狀態

uc/os是一個搶佔式多工的實時作業系統,每個任務都有各自的狀態,並且狀態之間都有一定的轉換關係。寫下此文以作記錄及幫助自己理清關係。 在uc/os-ii中,任務的狀態有5種:睡眠態、就緒態、執行態、等待態及中斷服務態。通過下圖可以有一個大致的認知: 最

最詳細的uC/OS-II 移植到STM32

這個圖表達了什麼資訊呢,其實就是告訴移植者需要將那些檔案移植到你的工程當中,首先是uC/OS-ii的原始檔,就是OS_CORE.C、OS_FLAG.C.....ucos_ii.H這些檔案,其實是uC/OS-ii的Port檔案,包括4個,分別是OS_CPU_C.C,OS_CPU_A.ASM,OS_CPU.H,O

uC/OS-II任務排程之就緒表及最高優先順序任務判定演算法

uC/OS-II是Jean J. Labrosse設計的完整的、可移植、可固化、可裁剪的搶佔式實時多工核心,絕大部分程式碼都是用標準的C語言編寫的,開源、規模不大,比較適合初次接觸嵌入式作業系統的人員