消息隊列
在了解消息隊列之前,先復習下數據結構的知識:隊列,插入和刪除受到限制的一種特殊線性表,只允許在后端進行插入操作,在前端進行刪除。
消息隊列是RTT系統中常用的一種通信結構,線程可以從隊列中讀取消息,如果隊列中沒有消息,則掛起線程。它是一種異步通信的方式。
由於隊列結構的特殊性,線程最先得到的消息是最先進入消息隊列的消息,遵循先進先出的原則(FIFO)。在RTT系統中,隊列可以傳遞不同長度的任意類型的消息,並且擁有直接向隊列頭發送消息的緊急處理機制。消息隊列最常見的用途就是進行線程間的信息交換。
來看看它的實現,首先是RTT中的控制塊定義:
/*消息隊列控制塊,在rtdef.h中定義*/ struct rt_messagequeue { struct rt_ipc_object parent; /**< inherit from ipc_object */ void *msg_pool; /**< start address of message queue */ rt_uint16_t msg_size; /**< message size of each message */ rt_uint16_t max_msgs; /**< max number of messages */ rt_uint16_t entry; /**< index of messages in the queue */ void *msg_queue_head; /**< list head */ void *msg_queue_tail; /**< list tail */ void *msg_queue_free; /**< pointer indicated the free node of queue */ rt_list_t suspend_sender_thread; /**< sender thread suspended on this message queue */ }; typedef struct rt_messagequeue *rt_mq_t;
從上到下依次為:
對象結構體
消息池開始地址
消息大小(字節),最大消息數目
記錄消息個數的變量
表頭指針,表尾指針,空閑節點指針
發送方線程掛起節點
再來看看它的相關函數:
/*創建函數,返回一個消息隊列句柄(rt_mq_t)*/ rt_mq_t rt_mq_create(const char *name, //名字 rt_size_t msg_size, //最大長度 rt_size_t max_msgs, //最大容量 rt_uint8_t flag) //模式,RTT中宏定義了一些模式 /*刪除函數*/ rt_err_t rt_mq_delete(rt_mq_t mq) //傳入句柄 /*發送消息函數*/ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size) //傳入分別為句柄,數據地址,數據大小(字節) /*接收消息函數*/ rt_err_t rt_mq_recv(rt_mq_t mq, //句柄 void *buffer, //讀取的位置 rt_size_t size, //接收的長度 rt_int32_t timeout) //等待時間
郵箱
郵箱是另一種常見的IPC通信(進程間通信)方式,相比於其他方式,其通信內容被限制在每一封郵件只能容納4字節的大小,換來的是其更低的開銷,更高的效率。
一封郵件恰好能容納STM32的一個指針,這樣,可以把指向緩沖區的指針作為郵件發送。(緩沖區:內存中預留的指定大小的空間,用來暫存輸入/輸出的數據)。也可以發送結構體指針。
郵箱亦遵循先進先出原則(FIFO)。
郵箱控制塊:
struct rt_mailbox { struct rt_ipc_object parent; /**< inherit from ipc_object */ rt_ubase_t *msg_pool; /**< start address of message buffer */ rt_uint16_t size; /**< size of message pool */ rt_uint16_t entry; /**< index of messages in msg_pool */ rt_uint16_t in_offset; /**< input offset of the message buffer */ rt_uint16_t out_offset; /**< output offset of the message buffer */ rt_list_t suspend_sender_thread; /**< sender thread suspended on this mailbox */ };
相關函數:
/*創建函數*/ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) /*刪除函數*/ rt_err_t rt_mb_delete(rt_mailbox_t mb) /*阻塞發送,當郵箱滿時,可以進行等待*/ rt_err_t rt_mb_send_wait(rt_mailbox_t mb, rt_ubase_t value, rt_int32_t timeout) /*非阻塞發送,不會等待,如果滿會返回錯誤值*/ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) /*接收*/ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)