消息隊(duì)列的應(yīng)用場(chǎng)景:
消息的主要作用——用于任務(wù)/線程、中斷服務(wù)例程之間的通信,主要是信息交換,他的一大特點(diǎn):可以接收長(zhǎng)度定制的消息。
隊(duì)列的主要作用——實(shí)現(xiàn)任務(wù)/線程、中斷服務(wù)例程之間的異步通信,所謂的異步通信的就是接收到消息可以先做緩存,不用立即處理,立即處理的話就叫同步通信,因?yàn)橐彺妫圆判枰?duì)列,你可以把隊(duì)列看成一種數(shù)據(jù)結(jié)構(gòu),實(shí)際上他也的確是數(shù)據(jù)結(jié)構(gòu),一般應(yīng)用鏈表來(lái)實(shí)現(xiàn)。
消息隊(duì)列控制塊——消息隊(duì)列狀態(tài)信息存儲(chǔ)
消息隊(duì)列控制塊的實(shí)現(xiàn)(站在應(yīng)用的角度是可以忽略這一部分,你只要知道他是一種數(shù)據(jù)類型就OK了):
struct rt_messagequeue
{
struct rt_ipc_object parent; /*它爸爸*/
void* msg_pool; /* 指向存放消息的緩沖區(qū)的指針 */
rt_uint16_t msg_size; /* 消息的長(zhǎng)度 */
rt_uint16_t max_msgs; /* 最大能夠容納的消息數(shù) */
rt_uint16_t entry; /* 隊(duì)列中已有的消息數(shù) */
void* msg_queue_head; /* 指針指向——消息鏈表頭 */
void* msg_queue_tail; /* 指針指向——消息鏈表尾 */
void* msg_queue_free; /* 指針指向——空閑消息鏈表 */
rt_list_t suspend_sender_thread; /* 發(fā)送線程的掛起等待隊(duì)列 */
};
typedef struct rt_messagequeue* rt_mq_t;
其實(shí)關(guān)于消息隊(duì)列控制塊,你只需要知道它和他的指針如何定義就夠了,重要的是:
struct rt_messagequeque msg_1; /*創(chuàng)建一個(gè)消息隊(duì)列控制塊對(duì)象*/
rt_mq_t *msg_1;/*創(chuàng)建一個(gè)消息隊(duì)列控制塊的引用*/
消息隊(duì)列的應(yīng)用API接口(只關(guān)注靜態(tài)類型,不要問(wèn)為什么不聊動(dòng)態(tài),問(wèn)就是不會(huì)。。。):
1.初始化消息隊(duì)列API(悄悄告訴你,其實(shí)初始化就是用一堆參數(shù)來(lái)初始化mq參數(shù)):
/*rt_err_t:用于判斷初始化是否成功的返回值,正常情況下返回:RT_EOK*/
rt_err_t rt_mq_init(rt_mq_t mq, /*消息隊(duì)列對(duì)象的句柄*/
const char* name, /*消息隊(duì)列的名稱*/
void *msgpool, /*指向存放消息的緩沖區(qū)的指針*/
rt_size_t msg_size, /*消息隊(duì)列中一條消息的最大長(zhǎng)度,單位字節(jié)*/
rt_size_t pool_size,/*存放消息的緩沖區(qū)大小*/
rt_uint8_t flag); /*消息隊(duì)列采用的等待方式,基本默認(rèn):RT_IPC_FLAG_PRIO*/
2.有初始化消息隊(duì)列API,就得有脫離消息隊(duì)列API(用的時(shí)候初始化,不用的時(shí)候要脫離):
/*rt_err_t:用于判斷脫離消息隊(duì)列是否成功的返回值,正常情況下返回:RT_EOK*/
rt_err_t rt_mq_detach(rt_mq_t mq);/*消息隊(duì)列對(duì)象的句柄*/
3.1發(fā)送一條消息到消息隊(duì)列,有多種API,主要區(qū)別發(fā)送是否需要等待超時(shí),發(fā)送消息是否為緊急消息,什么情況下發(fā)送不能用等待超時(shí)呢?(舉個(gè)栗子,中斷服務(wù)例程是不能才用等待超時(shí)發(fā)送的,于是就要才用第一種立即發(fā)送):
/*rt_err_t:發(fā)送消息到消息隊(duì)列是否成功,
消息隊(duì)列有空閑時(shí),發(fā)送成功:RT_EOK
消息隊(duì)列為滿時(shí),發(fā)送為滿:-RT_EFULL
發(fā)送消息大于消息隊(duì)列最大消息長(zhǎng)度時(shí),發(fā)送失敗:-RT_ERROR*/
rt_err_t rt_mq_send (rt_mq_t mq, /*消息隊(duì)列對(duì)象的句柄*/
void* buffer, /*發(fā)送消息內(nèi)容的指針*/
rt_size_t size);/*發(fā)送消息的大小*/
3.2采用等待超時(shí)方式發(fā)送消息到消息隊(duì)列API:
/*rt_err_t:發(fā)送消息到消息隊(duì)列是否成功,
消息隊(duì)列有空閑時(shí),發(fā)送成功:RT_EOK
消息隊(duì)列為滿時(shí),發(fā)送為滿:-RT_EFULL
發(fā)送消息大于消息隊(duì)列最大消息長(zhǎng)度時(shí),發(fā)送失敗:-RT_ERROR*/
rt_err_t rt_mq_send_wait(rt_mq_t mq, /*消息隊(duì)列對(duì)象的句柄*/
const void *buffer, /*發(fā)送消息內(nèi)容的指針*/
rt_size_t size, /*發(fā)送消息的大小*/
rt_int32_t timeout); /*超時(shí)時(shí)間*/
3.3才用緊急發(fā)送消息與第一種無(wú)等待發(fā)送很相似,不同的是消息被插入消息隊(duì)列的位置不一樣(緊急發(fā)送消息插入鏈表頭部,非緊急發(fā)送消息插入鏈表尾部):
/*rt_err_t:發(fā)送消息到消息隊(duì)列是否成功,
消息隊(duì)列有空閑時(shí),發(fā)送成功:RT_EOK
消息隊(duì)列為滿時(shí),發(fā)送為滿:-RT_EFULL
發(fā)送消息大于消息隊(duì)列最大消息長(zhǎng)度時(shí),發(fā)送失敗:-RT_ERROR*/
rt_err_t rt_mq_urgent (rt_mq_t mq, /*消息隊(duì)列對(duì)象的句柄*/
void* buffer, /*發(fā)送消息內(nèi)容的指針*/
rt_size_t size);/*發(fā)送消息的大小*/
4.從消息隊(duì)列中接收消息API:
/*rt_err_t:從消息隊(duì)列接收消息是否成功:RT_EOK
超時(shí):-RT_ETIMEOUT
接收失敗:-RT_ERROR*/
rt_err_t rt_mq_recv (rt_mq_t mq, /*消息隊(duì)列對(duì)象的句柄*/
void* buffer, /*接收消息的內(nèi)容指針*/
rt_size_t size,/*接收消息的大小*/
rt_int32_t timeout); /*超時(shí)時(shí)間*/
創(chuàng)建一個(gè)基于消息隊(duì)列的應(yīng)用:
1.關(guān)于消息隊(duì)列初始化應(yīng)用:
/* 消息隊(duì)列控制塊 */
static struct rt_messagequeue mq;
/* 消息隊(duì)列中用到的放置消息的內(nèi)存池 */
static rt_uint8_t msg_pool[2048];
rt_err_t result;
/* 初始化消息隊(duì)列 */
result = rt_mq_init(&mq,
"mqt",
&msg_pool[0], /* 內(nèi)存池指向 msg_pool */
1, /* 每個(gè)消息的大小是 1 字節(jié) */
sizeof(msg_pool), /* 內(nèi)存池的大小是 msg_pool 的大小 */
RT_IPC_FLAG_PRIO); /* 如果有多個(gè)線程等待,優(yōu)先級(jí)大小的方法分配消息 */
if (result != RT_EOK)
{
rt_kprintf("init message queue failed.\n");
return -1;
}
2.發(fā)送消息到消息隊(duì)列應(yīng)用:
int result;
char buf = 'A';
/* 發(fā)送消息到消息隊(duì)列中 */
result = rt_mq_send(&mq, &buf, 1);
if (result != RT_EOK)
{
rt_kprintf("rt_mq_send ERR\n");
}
3.從消息隊(duì)列接收消息應(yīng)用:
char buf = 0;
/* 從消息隊(duì)列中接收消息 */
if (rt_mq_recv(&mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
{
rt_kprintf("thread1: recv msg from msg queue, the content:%c\n", buf);
}