Message queue的結構如下:
1 Parent屬於內核對象,通過這個成員可以將消息隊列掛到系統對象容器里面. Parent其實是一個ipc結構體,里面包含了掛起的線程
初始化狀態如下:
2 msg_pool 是存放消息池的開始地址
3 msg_size 是每條消息的大小
4 max_msg 是最多的消息個數
5 entry:隊列中的消息索引,記錄消息隊列的消息個數
6 msg_queue_head/msg_queue_tail/msg_queue_free 鏈表頭,尾指針,以及指向空閑節點的指針
消息隊列初始化后狀態參考下圖。
消息發送
線程或者中斷服務程序都可以給消息隊列發送消息。當發送消息時,消息隊列對象先從空閑消息鏈表上取下一個空閑消息塊,把線程或者中斷服務程序發送的消息內容復制到消息塊上,然后把該消息塊掛到消息隊列的尾部。當且僅當空閑消息鏈表上有可用的空閑消息塊時,發送者才能成功發送消息;當空閑消息鏈表上無可用消息塊,說明消息隊列已滿,此時,發送消息的的線程或者中斷程序會收到一個錯誤碼(-RT_EFULL)
(a) 首先從空閑隊列中取出一個消息,如果空閑隊列中沒有可用信息塊了,消息隊列已滿,則返回-RT_EFULL。每次申請后msg_queue_free指針則后移
示意圖如下
(b) 取出消息后,將消息放到msg_queue_tail中去。並同時更新msg_queue_head的值
示意圖如下
(c) 此時在消息隊列中已經發送了消息。則看等待隊列是否有任務在等待消息。如果有的話則將任務從掛起列表中恢復,並開啟一次調度
消息接受
(a) 檢查隊列的消息是否為0,如果沒有消息且timeout ==0 則立即返回
(b) 如果消息隊列為空,但是等待時間大於0,則將當前任務掛起,並啟動一個定時器並發起一個線程調度
(c) 如果隊列中有消息。則從消息隊列頭部msg_queue_head中取出消息。並拷貝到指定的存儲地址buffer。拷貝消息的大小為size,大小不能超過創建消息隊列時候已經定義的消息大小msg_size.
示意圖如下:
獲取一個消息后,消息隊列上的頭鏈表消息被轉移到空閑消息鏈表中,這樣就可以保證消息隊列的循環利用。而不會導致頭鏈表指針移動到隊列尾部時沒有可用的消息節點。