FreeRTOS+POSIX之消息隊列API詳解

FreeRTOS+POSIX概述

可移植操作系統接口(Portable Operating System Interface,縮寫為POSIX)是IEEE為要在各種UNIX操作系統上運行軟件,而定義API的一系列互相關聯的標準的總稱,其正式稱呼為IEEE Std 1003,而國際標準名稱為ISO/IEC 9945。它基本上是Portable Operating System Interface(可移植操作系統接口)的縮寫,而X則表明其對Unix API的傳承。FreeRTOS + POSIX實現了POSIX線程 API 的子集。藉助FreeRTOS + POSIX,可以輕鬆將現有的POSIX兼容應用程序移植到FreeRTOS生態系統。FreeRTOS + POSIX部分實現了IEEE Std 1003.1-2017 Edition The Open Group Technical Standard Base Specification,Issue 7。

FreeRTOS + POSIX主要實現了任務管理、互斥量、條件變量、消息隊列和時鐘/定時器等POSIX接口功能。

FreeRTOS+POSIX之消息隊列API詳解

FreeRTOS+POSIX消息隊列

消息隊列提供一種任務間通信機制。消息隊列支持異步或者同步的消息通信,支持阻塞、非阻塞的消息發送和接收。提供創建、刪除、打開、關閉消息隊列以及發送、接受消息、限時發送、限時接受消息、獲取消息隊列屬性等應用編程接口。

mqd_t mq_open(const char * name,int oflag,mode_t mode,struct mq_attr * attr )

打開命名消息隊列

mq_open()用於創建一個新的命名消息隊列,或打開一個已存在的命名消息隊列。該接口的返回值稱為消息隊列描述符,其他接口可以用這個描述符來指定消息隊列。如果其他任務以同樣的名字調用該接口,那麼任務打開的消息隊列描述符將指向同一個消息隊列。

參數:

name:消息隊列名,其長度限制為 NAME_MAX,如果 name 不是已存在的消息隊列的名字, 並且 oflag 參數中沒有包含 O_CREAT 標誌,那麼該接口將失敗。

oflag:消息隊列選項,用來指定對消息隊列的接收和/或發送訪問權限。其值可以是O_RDWR, O_CREAT, O_EXCL, and O_NONBLOCK。

mode 該參數FreeRTOS系統不支持。

attr 參數用於指定消息隊列的屬性,如果 attr 為空,那就使用缺省屬性。

返回值:

執行成功返回消息隊列描述符;

(mqd_t)-1函數執行失敗,並設定 errno 指出錯誤。

int mq_close(mqd_t mqdes) 關閉命名消息隊列

mq_close()用於關閉一個命名的消息隊列。 該接口的功能與關閉一個已打開文件的 close函數類似,會解除消息隊列描述符 mqdes 和它的消息隊列間的關聯關係,調用任務關閉消息隊列後,將不能再使用該消息隊列描述符,但其消息隊列並不會從系統中刪除,除非已經有任務調用 mq_unlink()刪除了該消息隊列,並且當前對 mq_close()的調用關閉的是最後一個對消息隊列 mqdes 的引用。

參數

mqdes消息隊列描述符。

返回值:

0 函數執行成功;

-1 函數執行失敗,並設定 errno 指出錯誤。

int mq_unlink(const char * name) 刪除消息隊列

mq_unlink ()該接口用於刪除 name 指定的消息隊列。在成功調用 mq_unlink()後,如果在沒有設置oflag 中的 O_CREAT 標誌的情況下以 name 調用 mq_open(), 調用會失敗。在消息隊列沒有真正刪除前,以 name 調用 mq_open()重新創建消息隊列會返回新的消息隊列描述符。如果在調用 mq_unlink()時,有一個或多個任務打開了消息隊列,那麼消息隊列的刪除操作會推遲,直到所有對該消息隊列的引用都被關閉(即最後一個 mq_close()被調用), mq_unlink()調用會在刪除消息隊列名字後立即返回,不需要阻塞。

參數:

name 消息隊列名。

返回值:

0 函數執行成功;

-1 函數執行失敗,不會改變消息隊列,設定 errno 指出錯誤。

ssize_t mq_receive(mqd_t mqdes,char * msg_ptr,size_t msg_len,unsigned int * msg_prio )

接收消息

mq_receive()用來會從 mqdes 指定的消息隊列中接收最高優先級消息中最早的消息。如果由參數msg_len 指定的緩存區大小小於消息隊列屬性 mq_msgsize,調用會失敗並返回錯誤,否則,選定的消息會從隊列中刪除,並複製到 msg_ptr 指向的緩存區中。如果指定的消息隊列為空,且消息隊列描述符 mqdes 沒有設置 O_NONBLOCK 標誌位mq_receive()會阻塞,直到一個消息加入到隊列中或接口調用被信號中斷。如果有多個任務在等待接收消息,當消息到達時,等待的任務會按照消息隊列的屬性 mq_waitqtype 的設置來解除任務的阻塞。如果指定的消息隊列為空,且消息隊列描述符 mqdes 設置了 O_NONBLOCK 標誌位,則返回錯誤。

參數:

mqdes 消息隊列描述符;

msg_ptr 存放消息的緩存地址;

msg_len 存放消息的緩存區的長度;

msg_prio 消息的優先級,該參數FreeRTOS不支持。

返回值:

>0 函數執行成功,從隊列中刪除選定的消息,返回選定消息的字節長度;

-1 函數執行失敗,不刪除消息,設定 errno 指出錯誤。

int mq_send(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned msg_prio )

發送消息

mq_send ()用來將 msg_ptr 指向的消息添加到 mqdes 指定的消息隊列中。如果消息隊列已滿,且消息隊列描述符 mqdes 中沒有設置 O_NONBLOCK 標誌,那麼調用任務會阻塞,直到消息隊列空間可用或者調用被信號中斷;如果設置了 O_NONBLOCK 標誌,調用任務就不會阻塞,直接返回錯誤。如果有多個任務在等待發送,那麼在消息隊列空間可用時,等待的任務會按照消 息 隊 列 的 屬 性 mq_waitqtype 的 設 置 來 解 除 任 務 的 阻 塞 。 如 果 mq_waitqtype 設 置 為PTHREAD_WAITQ_PRIO , 則 按 照 優 先 級 策 略 解 除 任 務 的 阻 塞 ; 如 果 mq_waitqtype 設 置 為PTHREAD_WAITQ_FIFO,則按照 FIFO 的策略解除任務的阻塞。

參數:

mqdes 消息隊列描述符;

msg_ptr 存放消息的緩存地址;

msg_len 消息長度,其取值應小於等於消息隊列的 msg_msgsize 屬性,否則調用會失敗;

msg_prio 消息的優先級,該參數FreeRTOS不支持。

返回值:

0 函數執行成功;

-1 函數執行失敗,消息不會入隊,設定 errno 指出錯誤。

int mq_getattr(mqd_t mqdes,struct mq_attr * mqstat )獲取消息隊列屬性

該接口用來獲取消息隊列的屬性和狀態信息,結果會返回到參數 mqstat 引用的數據結構 mq_attr 中。接口調用成功後,結構變量 mqstat 的成員 mq_flags 被設置為打開消息隊列時設置的值; mq_maxmsg 和 mq_msgsize 被設置為打開消息隊列時所設置的值; mq_curmsgs 則被設置為消息隊列的當前狀態,標示當前隊列上的消息數。

參數:

mqdes 消息隊列描述符;

mqstat 存放消息隊列屬性的緩存地址。

返回值:

0 函數執行成功;

-1 函數執行失敗,設定 errno 指出錯誤。

ssize_tmq_timedreceive(mqd_tmqdes,char * msg_ptr,size_t msg_len,unsigned * msg_prio,const structtimespec* abstime )

限時接收消息

mq_timedreceive()的功能與 mq_receive()類似, 從 mqdes 指定的消息隊列中接收最高優先級消息最早的消息,但是如果任務在通過 mq_open()打開消息隊列時沒有設置O_NONBLOCK 標誌,且隊列中沒有適合接收的消息,那麼經過指定時間後會終止等待消息。如果設置了 O_NONBLOCK 標誌,那麼該接口等同於 mq_receive()。當調用任務阻塞等待超過了 abs_timeout 指定的絕對時間,或者調用該接口時已經過了 abs_timeout 指定的絕對時間,就會發生超時。如果任務調用該接口時可以立即從消息隊列中接收消息,就不會發生超時錯誤,並且不必檢查參數 abs_timeout 的合法性。

參數:

mqdes 消息隊列描述符;

msg_ptr 存放消息的緩存地址;

msg_len 存放消息的緩存區的長度;

msg_prio 消息的優先級,該參數FreeRTOS不支持。

abs_timeout 等待時間。

返回值:

>0 函數執行成功,從隊列中刪除選定的消息,並返回消息的字節長度;

-1 函數執行失敗,不刪除消息,設定 errno 指出錯誤。

int mq_timedsend(mqd_t mqdes,const char * msg_ptr,size_t msg_len,unsigned msg_prio,const struct timespec * abstime )

限時發送消息

mq_timedsend()的功能與 mq_send()類似,用來向 mqdes 指定的消息隊列中添加一個消息,但是如果指定消息隊列已滿,並且消息隊列描述符 mqdes 中沒有設置 O_NONBLOCK 標誌,那麼在超時到期時會終止任務的阻塞。如果消息隊列設置了 O_NONBLOCK 標誌,該接口等價於 mq_send()。當調用任務阻塞等待超過了 abs_timeout 指定的絕對時間,或者調用該接口時已經過了 abs_timeout指定的絕對時間,就會發生超時。如果接口調用時消息隊列中有足夠的空間使得消息可以立即添加到隊列中,那麼該接口將不會發生超時錯誤,並且不必檢查參數 abs_timeout 的合法性。

參數:

mqdes 消息隊列描述符;

msg_ptr 存放消息的緩存地址;

msg_len 消息長度;

msg_prio 消息的優先級,該參數FreeRTOS不支持;

abs_timeout 等待時間。

返回值:

0 函數執行成功, mq_send()和 mq_timedsend() 函數返回 0;

-1 函數執行失敗,消息不會入隊,設定 errno 指出錯誤。

消息隊列用例可參考FreeRTOS_plus_POSIX_demo.zip壓縮包中posix_demo.c文件。


分享到:


相關文章: