程序通訊學習筆記(Posix訊息佇列)
在某個程序往一個佇列寫入訊息之前,並不需要另外有個程序在該佇列上等待訊息的到達,這跟管道和FIFO是相反的,對於後兩者來說,除非讀出者已存在,否則先有寫入者是沒有意義的
1、mq_open、mq_close和mq_unlink函式
mq_open函式建立一個新的訊息佇列或者開啟一個已存在的訊息佇列
#include <mqueue.h>
mqd_t mq_open(const char *name, int oflags, .../*mode_t mode, struct mq_attr *attr*/);
成功返回訊息佇列描述字,失敗返回-1
oflags引數是O_RDONLY、O_WRONLY、O_RDWR之一,可能按位或上O_CREAT、O_EXCL或O_NONBLOCK
當操作是建立一個佇列時,mode和attr引數是需要的。attr引數用於給新佇列指定某些屬性,如果它為空指標,就使用預設屬性
訊息佇列描述字與檔案或套介面描述字是不一樣的
已開啟的訊息佇列用mq_close關閉
#include <mqueue.h>
int mq_close(mqd_t mqdes);
成功返回0,失敗返回-1
要從系統中刪除用作mq_open第一個引數的某個name,必須用mq_unlink
#include <mqueue.h>
int mq_unlink(const char *name);
成功返回0,失敗返回-1
編譯時注意:
(1)、新增目錄,掛載訊息佇列虛擬檔案系統
mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue
(2)、指定name時用這種形式/pathname
(3)、新增-lrt
2、mq_getattr和mq_setattr函式
每個訊息佇列有四個屬性,mq_getattr返回所有的這些屬性,mq_setattr則設定其中某個 屬性
#include <mqueue.h>
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, const struct mq_attr *attr, struct mq_attr *oattr);
成功返回0,失敗返回-1
mq_attr結構定義如下:
struct mq_attr
{
long mq_flags; //message queue flag:0, O_NONBLOCK
long mq_maxmsg; //佇列中允許的最大的訊息數目
long mq_msgsize;//單個訊息的最大大小
long mq_curmsgs;//當前訊息佇列中的訊息個數
};
指向某個mq_attr結構的指標可作為mq_open的第四個引數,從而允許在該函式的實際操作中建立一個訊息佇列,給它指定mq_maxmsg和mq_msgsize屬性.mq_open忽略該結構的另個兩個成員
mq_getattr把所指定佇列的當前屬性填入attr指向的結構
mq_setattr給指定的佇列設定屬性,只能設定mq_flags,每個佇列的最大訊息數和每個訊息的最大位元組數只能在建立時設定,當前訊息數則只能獲取不能設定
3、mq_send和mq_receive函式
每個訊息有一個優先順序,小於MQ_PRIO_MAX的無符號整數
mq_receive總是返回指定佇列中的優先順序最高的最早訊息,而且該優先順序能隨該訊息的內容及其長度返回
#include <mqueue.h>
int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio); 成功返回0,失敗返回-1
int mq_receive(mqd_t mqdes, char *ptr, size_t lne, unsigned int *prio); 成功返回訊息中的位元組數,失敗返回-1
4、訊息佇列的限制
有兩個限制:
(1) MQ_OPEN_MAX:一個程序同時開啟的訊息佇列的最大數目
(2)MQ_PRIO_MAX:任意訊息的最大優先順序值 加1
5、mq_notify函式
適用情況:往空佇列中放置了一個訊息
兩種方式 :
(1)產生一個訊號
(2)建立一個執行緒執行一個指定的函式
函式定義
#include <mqueue.h>
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
成功返回0,失敗返回 -1
訊號常值 都 定義在<signal.h>標頭檔案中
union sigval
{
int sival_int;
void *sival_ptr;
};
struct sigevent
{
int sigev_notify;//通知型別,有SIGEV_(NONE, SIGNAL, THREAD)
int sigev_signo;//SIGEV_SIGNAL時的訊號值
uniong sigval sigev_value;//傳遞給訊號處理函式或者執行緒的值
void (*sigev_notify_function)(union sigval);
pthread_attr_t *sigev_notify_attributes;
};
函式的若干規則:
(1)notification非空,表示有一個訊息到達該佇列並且先前為空時得到通知
(2)notification為空,表示註冊被撤銷
(3)任意時刻只有一個程序可以註冊為接收某個佇列的通知
(4)當有一個訊息到達先前為空的佇列時,且有一個程序註冊為接收該佇列的通知時,只有沒有任何執行緒阻塞在該佇列的mq_receive呼叫的前提下,通知才會發出。即mq_receive呼叫 中的阻塞優先於任何通知的註冊
(5)當通知傳送給註冊程序時,其註冊被撤銷,須再次呼叫 mq_notify註冊