訊息佇列可以認為是乙個訊息列表。執行緒可以往訊息佇列中放置訊息或者取出訊息。每個訊息都是一條記錄,由傳送者賦予乙個優先順序。乙個程序在往乙個訊息佇列中寫入訊息之前,不需要有某個程序在該佇列上等待訊息到達(這跟管道和fifo是相反的)。
訊息佇列具有隨核心的持續性, 也就是說在核心重新啟動之前,不管發訊息的程序或者取訊息的程序是否結束,訊息佇列是始終存在的。
訊息佇列有兩種,分別是posix訊息佇列和system v訊息佇列, 下面的例程是posix訊息佇列的使用。
// 1.c
#include#include#define file_mode (s_irusr|s_iwusr|s_irgrp|s_iroth)
int main(int argc, char* ar**)
// null 表示採用預設屬性
mdq = mq_open(ar**[1], flag, file_mode, null);
return 0;
}
以上是乙個建立訊息佇列的例程,使用如下命令進行編譯得到可執行檔案a.out
gcc -g 1.c -wall -lrt
執行以下命令,即可得到乙個名為temp.1234的訊息佇列, 這個訊息佇列儲存在/dev/mqueue中
./a.out /temp.1234
[root@localhost ipc]# ll /dev/mqueue/
total 0
-rw-r--r--. 1 root root 80 nov 9 06:59 temp.1234
注意訊息佇列的名字必須以』/'開頭,才能建立成功。
刪除訊息佇列使用mq_unlink函式.
// 2.c
#include#includeint main(int argc, char* ar**)
int ret = mq_unlink(ar**[1]);
printf("%d\n", ret);
return 0;
}
編譯
gcc -g 2.c -wall -lrt
執行
./a.out /temp.1234
執行完之後,可以看到剛才建立的訊息佇列已經被刪除了。
[root@localhost ipc]# ll /dev/mqueue/
total 0
每個訊息佇列有四個屬性,mq_getattr函式返回所有這些屬性。
struct mq_attr ;
// 3.c
#include#includeint main(int argc, char* ar**)
mqd = mq_open(ar**[1], o_rdonly);
mq_getattr(mqd, &attr);
printf("max msgs = %ld\nmax bytes/msg = %ld\ncurrently on queue = %ld\n",
attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
mq_close(mqd);
return 0;
}
編譯執行,檢視我們剛才建立的訊息佇列的屬性
gcc -g 3.c -wall -lrt
./a.out /temp.1234
max msgs = 10
max bytes/msg = 8192
currently on queue = 0
可以看到我們建立的訊息佇列最多容納10條訊息,每條訊息最多8192位元組,當前佇列上一條訊息也沒有。
mq_setattr函式給佇列設定屬性,但是只使用mq_attr結構中的mq_flags欄位以設定或者清除非阻塞標誌位, 這個結構的其他三個成員均被忽略。
如果希望設定最大訊息數量和每條訊息的最大位元組數量,需要在建立佇列的時候指定。
在前面的例子當中,以預設屬性建立的佇列所能容納的最大訊息數量是10, 每條訊息最多8192個位元組。現在,我們嘗試以我們自己指定的屬性建立佇列。
// 4.c
#include#include#define file_mode (s_irusr|s_iwusr|s_irgrp|s_iroth)
struct mq_attr attr;
int main(int argc, char* ar**)
attr.mq_maxmsg = 20;
attr.mq_msgsize = 4096;
mdq = mq_open(ar**[1], flag, file_mode, &attr);
mq_close(mdq);
return 0;
}
在這個例子當中,我們設定最大的訊息數量是20, 每條訊息最多4096個位元組。
編譯執行,並檢視一下屬性
max msgs = 20
max bytes/msg = 4096
currently on queue = 0
可以看到,這次我們建立了乙個不同的訊息佇列。
這兩個函式用於向乙個佇列新增和取出訊息。每個訊息有乙個優先順序, mq_receive總是返回佇列中最高優先順序的最早訊息, 而且該優先順序可以隨該訊息的內容和長度一併返回。
傳送
// send
#include
#include
#include
#include
intmain
(int argc,
char
* ar**)
priorty =
atoi
(ar**[3]
); mqd =
mq_open
(ar**[1]
, o_wronly)
;int ret =
mq_send
(mqd, ar**[2]
,strlen
(ar**[2]
), priorty);if
(ret !=0)
mq_close
(mqd)
;return0;
}
接收
// receive
#include#include#includestruct mq_attr attr;
int main(int argc, char* ar**)
mqd = mq_open(ar**[1], o_rdonly);
mq_getattr(mqd, &attr);
printf("size = %ld\n", attr.mq_msgsize);
buff = malloc(attr.mq_msgsize);
cnt = mq_receive(mqd, buff, attr.mq_msgsize, &priorty);
printf("received %d bytes, priority = %u\n", cnt, priorty);
printf("message = %s\n", (char*)buff);
mq_close(mqd);
return 0;
}
訊息佇列的實現定義了兩個限制:
這兩個值通常定義在中,可以通過sysconf函式得到
#include#includeint main()
在linux下執行得到的結果是
mq_open_max = -1
mq_prio_max = 32768
-1 表示對數量沒有限制 IPC 訊息佇列
include int msgget key t key,int msg 返回值 若成功,返回訊息佇列id 若出錯返回 1 與其他ipc機制一樣,需要提供乙個鍵值key來命名某個特定的訊息佇列。可通過ftok 來生成。msg 表示訊息佇列訪問許可權。可與兩個巨集配合進行操作 ipc creat 如果...
IPC之訊息佇列
訊息佇列缺點 1.如果程序建立了乙個訊息佇列,在該佇列中放入了幾則訊息,然後終止,但是該訊息佇列及其內容並不會被刪除。直到出現一下情況 某個程序呼叫msgrcv或 msgctl讀訊息或刪除訊息佇列,某個程序執行ipcrm 1 命令刪除訊息佇列,或由正在啟動的系統刪除訊息佇列。2.訊息佇列有大小限制,...
IPC之訊息佇列
可閱讀mq overview查閱更多資訊 man 7 mq overview.posix的訊息佇列實現更好,但systemv的訊息佇列更廣泛應用 舊的api posix的訊息佇列有兩種呼叫方式 庫函式和系統呼叫。訊息佇列是乙個訊息的鏈結列表,訊息都儲存在核心中,程序通過一種和共享記憶體使用的識別符號...