IPC 訊息佇列

2021-09-29 11:58:51 字數 3980 閱讀 5433

訊息佇列可以認為是乙個訊息列表。執行緒可以往訊息佇列中放置訊息或者取出訊息。每個訊息都是一條記錄,由傳送者賦予乙個優先順序。乙個程序在往乙個訊息佇列中寫入訊息之前,不需要有某個程序在該佇列上等待訊息到達(這跟管道和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的訊息佇列有兩種呼叫方式 庫函式和系統呼叫。訊息佇列是乙個訊息的鏈結列表,訊息都儲存在核心中,程序通過一種和共享記憶體使用的識別符號...