IPC之訊息佇列

2021-09-08 22:24:56 字數 4474 閱讀 9132

可閱讀mq_overview查閱更多資訊:man 7 mq_overview.

posix的訊息佇列實現更好,但systemv的訊息佇列更廣泛應用(舊的api)。

posix的訊息佇列有兩種呼叫方式:庫函式和系統呼叫。

訊息佇列是乙個訊息的鏈結列表,訊息都儲存在核心中,程序通過一種和共享記憶體使用的識別符號同種類的識別符號標識訊息。如果你把乙個訊息新增到乙個佇列,佇列顯示出fifo的特性,因為新訊息被新增到佇列的末尾。但是,和fifo不同,佇列中的訊息能夠以有些隨意的順序進行檢索,因為,可以通過乙個訊息的型別把訊息從佇列中檢索出來。從這方面看,佇列在程式設計上類似於結合陣列。

system v的訊息佇列包含如下函式:msgget,msgsnd,msgrcv,msgctl。

#include

#include

#include

int msgget(key_t key, int flags);  //flags中可呼叫標準八進位制記法規定所有使用者擁有的許可權。

#include #include 

#include

#include

#include

#include

int main(int argc, char *ar**)

printf(

"created queue id = %d\n

", qid);

if((qid == msgget(key, 0)) < 0

)

printf(

"opened queue id =%d\n

", qid);

exit(exit_success);

}

把乙個新訊息新增到佇列的末尾,可以使用msgsnd函式,

int msgsnd(int msgid, const void *prt, size_t nbytes, int flags);

ptr指向msgbuf機構體,

struct msgbuf;

int main(int argc, char *ar**)

qid = atoi(ar**[1

]); puts(

"enter message to post:");

if((fgets((&pmsg)->msg_text, bufsz, stdin)) ==null)

pmsg.msg_type =getpid();

len =strlen(pmsg.msg_text);

if((msgsnd(qid, &pmsg, len, 0)) < 0

)

puts(

"message posted");

exit(exit_success);

}

~$./a.out

created queue id = 32768

opened queue id =32768

~$ipcs -q

------ message queues --------key msqid owner perms used-bytes messages

0x0000007b

32768 yuxi 666

00

~$gcc qsnd.c -wall

~$./a.out

32768

enter message to post:

yuyuyu

message posted

~$ipcs -q

------ message queues --------key msqid owner perms used-bytes messages

0x0000007b

32768 yuxi 666

71

讀取佇列中的訊息用msgrcv,

int msgrcv(int msgid, void *ptr, size_t nbytes, long type, int flags);

如果執行成功,msgrcv刪除從佇列返回的訊息。它的引數和msgsnd接受的引數一樣,差別在於msgrcv用訊息型別和多達nbytes位元組的資料填入ptr結構。另外type和前面討論的msg結構的成員msg_type相對應。type的值決定了返回哪個訊息,如下所述:

>如果type是0,返回佇列中的第一條訊息(最上面的一條訊息)。

>如果type大於0,返回msg_type等於type的第一條訊息。

>如果type小於0,返回msg_type為小於等於type絕對值的最小值的第一條訊息。

flags的值也控制著msgrcv的行為。如果flags中設定了msg_noerror位,那麼如果返回的訊息比nbytes位元組多,訊息就會被截斷到nbytes位元組(但不會產生提示說訊息被截短)。否則,msgrcv返回-1表明出錯並且設定errno變數的值為e2big。訊息仍舊儲存在佇列中。

注意:引數type的負值也可以用於建立乙個lifo,即先入後出型別的佇列,這也就是棧。在type中傳遞負值能夠讓你在佇列中以逆序檢索某種型別的訊息。

#include #include 

#include

#include

#include

#include

#include

#define bufsz 512

struct

msg;

int main(int argc, char *ar**)

qid = atoi(ar**[1

]); len = msgrcv(qid, &pmsg, bufsz, 0, 0

);

if(len <= 0

)

(&pmsg)->msg_text[len] = '\0'

; printf(

"reading queue id: %05d\n

", qid);

printf(

"message type: %05ld\n

", pmsg.msg_type);

printf(

"message length: %d bytes\n

", len);

printf(

"message text: %s\n

", pmsg.msg_text);

exit(exit_success);

}

~$ipcs -q

------ message queues --------key msqid owner perms used-bytes messages

0x0000007b

32768 yuxi 666

142

~$./a.out

32768

reading queue id:

32768

message type:

04927

message length:

7bytes

message text: yuyuyu

~$./a.out

32768

reading queue id:

32768

message type:

04985

message length:

7bytes

message text: yuyuyu

~$ipcs -q

------ message queues --------key msqid owner perms used-bytes messages

0x0000007b

32768 yuxi 666

00

msgctl函式提供了對訊息佇列一定程度的控制功能,

int msgctl(int msgid, int cmd, struct msqid_ds *buf);

一般而言,msgid是乙個已經存在的佇列id。cmd可以為如下值之一:

>ipc_rmid--刪除佇列msgid。

>ipc_stat--用佇列的msqid_ds結構填充buf,這是一種非破壞性讀操作。

>ipc_set--可改變佇列的uid、gid、訪問模式和佇列的最大位元組數。

初始化舉例:

int init_msq(const

char *path, int

proj)

return msgget(key, ipc_creat | 0600

);}

注:大部分內容摘自《gnu/linux程式設計指南》

IPC之訊息佇列

訊息佇列缺點 1.如果程序建立了乙個訊息佇列,在該佇列中放入了幾則訊息,然後終止,但是該訊息佇列及其內容並不會被刪除。直到出現一下情況 某個程序呼叫msgrcv或 msgctl讀訊息或刪除訊息佇列,某個程序執行ipcrm 1 命令刪除訊息佇列,或由正在啟動的系統刪除訊息佇列。2.訊息佇列有大小限制,...

IPC之訊息佇列

一.特點 1.訊息佇列有特定的格式和優先順序 3.佇列裡可實現隨機查詢資訊,也可以按照資訊型別查詢 msgtpye 二.寫出 讀入都存到乙個結構體中 struct msgbuf 例如 struct msgbuf readbuf,sendbuf 三.四個必須知道的函式 1.得到訊息佇列識別符號或建立乙...

IPC 訊息佇列

include int msgget key t key,int msg 返回值 若成功,返回訊息佇列id 若出錯返回 1 與其他ipc機制一樣,需要提供乙個鍵值key來命名某個特定的訊息佇列。可通過ftok 來生成。msg 表示訊息佇列訪問許可權。可與兩個巨集配合進行操作 ipc creat 如果...