日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux进程间通讯之消息队列

發(fā)布時(shí)間:2024/9/30 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux进程间通讯之消息队列 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先有個(gè)大體的概念:http://www.xefan.com/archives/83703.html

頭文件: #include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>

函數(shù): key_t ftok(const char *filename, int proj_id);
通過文件名和項(xiàng)目號(hào)獲得System V IPC鍵值(用于創(chuàng)建消息隊(duì)列、共享內(nèi)存所用)
proj_id:項(xiàng)目號(hào),不為0即可
返回:成功則返回鍵值,失敗則返回-1

函數(shù): int msgget(key_t key, int msgflg);
key:鍵值,當(dāng)為IPC_PRIVATE時(shí)新建一塊共享內(nèi)存;
shmflg:標(biāo)志。
IPC_CREAT:內(nèi)存不存在則新建,否則打開;
IPC_EXCL:只有在內(nèi)存不存在時(shí)才創(chuàng)建,否則出錯(cuò)。
返回:成功則返回標(biāo)識(shí)符,出錯(cuò)返回-1

函數(shù): int msgsnd(int msgid, const void *msgp, size_t sz, int flg);
向消息隊(duì)列發(fā)送消息
msgid:通過msgget獲取
msgp:指向消息內(nèi)容的指針
sz:消息內(nèi)容的大小
flg:處理方式;如為IPC_NOWAIT時(shí)表示空間不足時(shí)不會(huì)阻塞
返回:成功則返回0,失敗返回-1

函數(shù): int msgrcv(int msgid, void *msgp, size_t sz, long type, int flg);
從消息隊(duì)列讀取消息
msgid:通過msgget獲取
msgp:指向消息內(nèi)容的指針
sz:消息內(nèi)容的大小
type:指定接收的消息類型;若為0則隊(duì)列第一條消息將被讀取,而不管類型;若大于0則隊(duì)列中同類型的消息將被讀取,如在flg中設(shè)了MSG_RXCEPT位將讀取指定類型的其他消息;若小于0讀取絕對(duì)值小于type的消息。
flg:處理方式;
返回:成功返回收到消息長度,錯(cuò)誤返回-1

函數(shù): int msgctl(int msgid, int cmd, struct msgid_ds *buf);
msgid:通過msgget獲取
cmd:控制命令,如下:
IPC_STAT:獲取消息隊(duì)列狀態(tài)
IPC_SET:改變消息隊(duì)列狀態(tài)
IPC_RMID:刪除消息隊(duì)列
buf:結(jié)構(gòu)體指針,用于存放消息隊(duì)列狀態(tài)
返回:成功返回與cmd相關(guān)的正數(shù),錯(cuò)誤返回-1

注意:消息隊(duì)列一旦創(chuàng)建就會(huì)一直存在系統(tǒng)中,直到手動(dòng)刪除或者重啟系統(tǒng)。可以使用ipcs -q命令來查看系統(tǒng)存在的消息隊(duì)列。

/****************************************** 使用消息隊(duì)列進(jìn)行進(jìn)程通信——寫進(jìn)程* 該進(jìn)程用于創(chuàng)建信號(hào)量* 龍昌博客:http://www.xefan.com*****************************************/ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h>typedef struct _msg_buf{long type; //消息類型char buf[100]; //消息內(nèi)容 } msg_buf;int main() {int key, qid;msg_buf buf;key = ftok("tmp", 10);qid = msgget(key, IPC_CREAT);printf("key: %d\nqid: %d\n", key, qid);buf.type = 10;while (1){fgets(buf.buf, 100, stdin);if (msgsnd(qid, (void *)&buf, 100, 0) < 0){perror("msgsnd");exit(-1);}}return 0; }
/****************************************** 使用消息隊(duì)列進(jìn)行進(jìn)程通信——讀進(jìn)程* 該進(jìn)程用于創(chuàng)建信號(hào)量* 龍昌博客:http://www.xefan.com*****************************************/ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h>typedef struct _msg_buf{long type; //消息類型char buf[100]; //消息內(nèi)容 } msg_buf;int main() {int key, qid;msg_buf buf;key = ftok("tmp", 10);qid = msgget(key, IPC_CREAT);printf("key: %d\nqid: %d\n", key, qid);while (1){if (msgrcv(qid, (void *)&buf, 100, 0, 0) < 0){perror("msgrcv");exit(-1);}printf("type:%d\nget:%s\n", buf.type, buf.buf);}return 0; }
先運(yùn)行寫進(jìn)程再運(yùn)行讀進(jìn)程。



轉(zhuǎn)自:http://blog.csdn.net/liranke/article/details/5608686


很詳細(xì)


1.?基本概念

消息隊(duì)列的最佳定義是:內(nèi)核地址空間中的內(nèi)部鏈表。消息可以順序地發(fā)送到隊(duì)列中,

并以幾種不同的方式從隊(duì)列中獲取。當(dāng)然,每個(gè)消息隊(duì)列都是由?IPC標(biāo)識(shí)符所唯一標(biāo)識(shí)的。

2.?內(nèi)部和用戶數(shù)據(jù)結(jié)構(gòu)

要完成理解象系統(tǒng)?V IPC這樣復(fù)雜的問題,關(guān)鍵是要徹底熟悉內(nèi)核的幾個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)。

甚至對(duì)那些最基本的操作來說,直接訪問這些結(jié)構(gòu)中的某幾個(gè)結(jié)構(gòu)也是必要的,而其他的結(jié)

構(gòu)則停留在一個(gè)更低的級(jí)別上。

3.?消息緩沖區(qū)

我們要介紹的第一個(gè)結(jié)構(gòu)是?msgbuf結(jié)構(gòu)。這個(gè)特殊的數(shù)據(jù)結(jié)構(gòu)可以認(rèn)為是消息數(shù)據(jù)的模

板。雖然定義這種類型的數(shù)據(jù)結(jié)構(gòu)是程序員的職責(zé),但是讀者絕對(duì)必須知道實(shí)際上存在

msgbuf類型的結(jié)構(gòu)。它是在在?linux/msg.h中定義的,有2個(gè)成員:

? mtype它是消息類型,以正數(shù)來表示。這個(gè)數(shù)必須為一個(gè)正數(shù)!

? mtext它就是消息數(shù)據(jù)。

?

4.?內(nèi)核msg結(jié)構(gòu)

內(nèi)核把消息隊(duì)列中的每個(gè)消息都存放在?msg結(jié)構(gòu)的框架中。該結(jié)構(gòu)是在?linux/msg.h中定義

的,如下是其成員的描述:

? msg_next這是一個(gè)指針,指向消息隊(duì)列中的下一個(gè)消息。在內(nèi)核尋址空間中,它們

是當(dāng)作一個(gè)鏈表存儲(chǔ)的。

? msg_type這是消息類型,它的值是在用戶結(jié)構(gòu)?msgbuf中賦予的。

? msg_spot這是一個(gè)指針,指向消息體的開始處。

? msg_ts這是消息文本(消息體)的長度。

??內(nèi)核?msgid_ds結(jié)構(gòu)IPC對(duì)象分為三類,每一類都有一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu),該數(shù)據(jù)結(jié)構(gòu)

是由內(nèi)核維護(hù)的。對(duì)于消息隊(duì)列而言,它的內(nèi)部數(shù)據(jù)結(jié)構(gòu)是???????????????msqid_ds結(jié)構(gòu)。對(duì)于系統(tǒng)上

創(chuàng)建的每個(gè)消息隊(duì)列,內(nèi)核均為其創(chuàng)建、存儲(chǔ)和維護(hù)該結(jié)構(gòu)的一個(gè)實(shí)例。該結(jié)構(gòu)在

linux/msg.h中定義,如下所示:

struct msqid_ds{

??? struct ipc_perm ??? msg_perm;??

??? msgqnum_t ? msg_qnum;??????

??? msglen_t??? msg_qbytes; ???

??? pid_t?????? msg_lspid;?????

??? pid_t ????? msg_lrpid;????? ???

??? time_t????? msg_stime;?????

??? time_t????? msg_rtime;?????

??? time_t????? msg_ctime;?????

??? ...

???

??? ...

};

?

?

?

在不同的系統(tǒng)中,此結(jié)構(gòu)會(huì)有不同的新成員,這里只列出最少擁有的關(guān)鍵成員。其中,msg_qbytes成員以及msg_qnum成員在不同的系統(tǒng)也會(huì)有不同的上限值,這里就不逐一介紹了,詳細(xì)內(nèi)容請(qǐng)參閱相關(guān)系統(tǒng)手冊(cè)。

? msg_perm它是?ipc_perm結(jié)構(gòu)的一個(gè)實(shí)例,?ipc_perm結(jié)構(gòu)是在?linux/ipc.h中定義的。

該成員存放的是消息隊(duì)列的許可權(quán)限信息,其中包括訪問許可信息,以及隊(duì)列的創(chuàng)建者

的有關(guān)信息?(uid等等)

? msg_first鏈接到隊(duì)列中的第一個(gè)消息?(列表頭部?)

? msg_last鏈接到隊(duì)列中的最后一個(gè)消息?(列表尾部)

? msg_stime發(fā)送到隊(duì)列的最后一個(gè)消息的時(shí)間戳?(time_t)

? msg_rtime從隊(duì)列中獲取的最后一個(gè)消息的時(shí)間戳。

? msg_ctime對(duì)隊(duì)列進(jìn)行最后一次變動(dòng)的時(shí)間戳。

?

?

5.?內(nèi)核ipc_perm結(jié)構(gòu)

內(nèi)核把IPC對(duì)象的許可權(quán)限信息存放在?ipc_perm類型的結(jié)構(gòu)中。例如在前面描述的某個(gè)消

息隊(duì)列的內(nèi)部結(jié)構(gòu)中,?msg_perm成員就是?ipc_perm類型的,它的定義是在文件?linux/ipc.h中,

?

以上所有的成員都具有相當(dāng)?shù)淖詳U(kuò)展性。對(duì)象的創(chuàng)建者以及所有者?(它們可能會(huì)有不同?)

有關(guān)信息,以及對(duì)象的?IPC關(guān)鍵字都是存放在該結(jié)構(gòu)中的。八進(jìn)制形式的訪問模式也是存放在

這里的,它是以一種無符號(hào)短整型的形式存儲(chǔ)的。最后,時(shí)間片使用序列編號(hào)存放在最后面,

每次通過系統(tǒng)調(diào)用關(guān)閉?IPC對(duì)象(摧毀)時(shí),這個(gè)值將被增加一,至多可以增加到能駐留在系統(tǒng)

中的IPC對(duì)象的最大數(shù)目。用戶需要關(guān)心這個(gè)值嗎?答案是

有關(guān)這個(gè)問題,在?Richard Stevens所著的《?Unix Network Programming?》一書的第125

中作了精辟的討論。該書還介紹了?ipc_perm結(jié)構(gòu)的存在和行為在安全性方面的原因。

?

6.?創(chuàng)建消息隊(duì)列:

1?msgget簡(jiǎn)介:為了創(chuàng)建一個(gè)新的消息隊(duì)列,或者訪問一個(gè)現(xiàn)有的隊(duì)列,可以使用系統(tǒng)調(diào)用?msgget ( )


msgget ( )的第一個(gè)變?cè)顷P(guān)鍵字的值?(在我們的例子中該值是調(diào)用?ftok ( )的返回值)。這個(gè)

關(guān)鍵字的值將被拿來與內(nèi)核中其他消息隊(duì)列的現(xiàn)有關(guān)鍵字值相比較。比較之后,打開或者訪

問操作依賴于msgflg變?cè)膬?nèi)容。

? IPC_CREAT如果在內(nèi)核中不存在該隊(duì)列,則創(chuàng)建它。

? IPC_EXCL當(dāng)與IPC_CREAT一起使用時(shí),如果隊(duì)列早已存在則將出錯(cuò)。

如果只使用了?IPC_CREAT, msgget ( )或者返回新創(chuàng)建消息隊(duì)列的消息隊(duì)列標(biāo)識(shí)符,或者


會(huì)返回現(xiàn)有的具有同一個(gè)關(guān)鍵字值的隊(duì)列的標(biāo)識(shí)符。如果同時(shí)使用了


I P C _ E X C L?IPC_CREAT,那么將可能會(huì)有兩個(gè)結(jié)果。或者創(chuàng)建一個(gè)新的隊(duì)列,或者如果該隊(duì)列存在,則

調(diào)用將出錯(cuò),并返回-1IPC_EXCL本身是沒有什么用處的,但在與IPC_CREAT組合使用時(shí),

它可以用于保證沒有一個(gè)現(xiàn)存的隊(duì)列為了訪問而被打開。

有個(gè)可選的八進(jìn)制許可模式,它是與掩碼進(jìn)行?OR操作以后得到的。這是因?yàn)閺墓δ苌现v,

每個(gè)IPC對(duì)象的訪問許可權(quán)限與?Unix文件系統(tǒng)的文件許可權(quán)限是相似的!

?

2msgget舉例:

下面實(shí)例演示了使用msgget函數(shù)創(chuàng)建一個(gè)隊(duì)列,函數(shù)中參數(shù)falgs指定為IPC_CREAT|0666,說明新建一個(gè)權(quán)限為0666的消息隊(duì)列,其中組用戶、當(dāng)前用戶以及其他用戶擁有讀寫的權(quán)限。并在程序的最后使用shell命令ipcs –q來查看系統(tǒng)IPC的狀態(tài)。

1)在vi編輯器中編輯該程序如下:

程序清單14-12? create_msg.c msgget函數(shù)

#include <sys/msg.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <stdio.h>

#include <stdlib.h>

int main ( void )

{

??? int???? qid;

??? key_t?????? key;

???

??? key = 113;

??? qid=msgget( key, IPC_CREAT | 0666 )?????? /*創(chuàng)建一個(gè)消息隊(duì)列*/

??? if ( qid < 0 ) {??????????????????????????? /*?創(chuàng)建一個(gè)消息隊(duì)列失敗?*/

??????? perror ( "msgget" );

??????? exit (1) ;

??? }

???

??? printf ("created queue id : %d /n", qid );? /*?輸出消息隊(duì)列的ID */

???

??? system( "ipcs -q" );??????????????????????? /*查看系統(tǒng)IPC的狀態(tài)*/

??? exit ( 0 );

}

2)在shell中編譯該程序如下:

$gcc create_msg.c–o create_msg

3)在shell中運(yùn)行該程序如下:

$./ create_msg

created queue id : 0

------ Message Queues --------

key??????? msqid????? owner????? perms????? used-bytes?? messages

0x0000af40 623430?? root?? ??? 666??????? 0??????????? 0

0x0000007b 0????????? root?? ????666??????? 0??????????? 0

在程序中使用了系統(tǒng)命令ipcs,命令參數(shù)-q說明只查看消息隊(duì)列的狀態(tài)。注意在輸出消息中,key段標(biāo)明的是IPCkey值,msqid為該隊(duì)列的ID值,perms為執(zhí)行權(quán)限。同樣,隊(duì)列的執(zhí)行權(quán)限像其他IPC對(duì)象一樣沒有執(zhí)行權(quán)限。函數(shù)msgctl可以在隊(duì)列上做多種操作,函數(shù)原型如下:

#include <sys/msg.h>

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

參數(shù)msqid為指定的要操作的隊(duì)列,cmd參數(shù)指定所要進(jìn)行的操作,其中有些操作需要buf參數(shù)。cmd參數(shù)的詳細(xì)取值及操作如表14-9所示。

14-9? cmd參數(shù)詳解

cmd

????

IPC_STAT

取隊(duì)列的msqid_ds結(jié)構(gòu),將它存放在buf所指向的結(jié)構(gòu)中(需要buf參數(shù))

IPC_SET

使用buf所指向結(jié)構(gòu)中的值對(duì)當(dāng)前隊(duì)列的相關(guān)結(jié)構(gòu)成員賦值,其中包括:msg_perm.uidmsg_perm.gidmsg_perm.mode以及msg_perm.cuid。該命令只能由具有以下條件的進(jìn)程執(zhí)行:進(jìn)程有效用戶ID等于msg_perm.cuidmsg_perm.uid超級(jí)用戶進(jìn)程。其中只有超級(jí)用戶才可以增加隊(duì)列的msg_qbytes的值

IPC_RMID

刪除隊(duì)列,并清除隊(duì)列中的所有消息。此操作會(huì)影響后續(xù)進(jìn)程對(duì)這個(gè)隊(duì)列的相關(guān)操作。該命令只能由具有以下條件的進(jìn)程執(zhí)行。進(jìn)程有效用戶ID等于msg_perm.cuidmsg_perm.uid,超級(jí)用戶進(jìn)程

下面實(shí)例演示了調(diào)用msgctl函數(shù)操作隊(duì)列,程序中先讀取命令行參數(shù),如沒有,則打印命令提示信息,在調(diào)用msgctl函數(shù)執(zhí)行刪除操作的前后分別調(diào)用了一次shell命令ipcs –q來查看系統(tǒng)IPC的狀態(tài)。

1)在vi編輯器中編輯該程序如下:

程序清單14-13? del_msg.c?調(diào)用msgctl刪除指定隊(duì)列

#include <sys/msg.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <stdio.h>

#include <stdlib.h>

int main ( int argc ,char *argv[] )

{

??? int qid ;

???

??? if ( argc != 2 ){ /*?命令行參數(shù)出錯(cuò)?*/

??????? puts ( "USAGE: del_msgq.c <queue ID >" );

??????? exit ( 1 );

??? }

???

??? qid = atoi ( argv[1] ); /*?通過命令行參數(shù)得到組ID */

??? system( "ipcs -q");

???

??? if ( ( msgctl( qid, IPC_RMID, NULL ) ) < 0 ){ /*?刪除指定的消息隊(duì)列?*/

??????? perror ("msgctl");

??????? exit (1 );

??? }

??? system( "ipcs -q");

??? printf ( "successfully removed %d? queue/n", qid ); /*?刪除隊(duì)列成功?*/

??? exit( 0 );

}

2)在shell中編譯該程序如下:

$gcc del_msg.c–o del_msg

3)在shell中運(yùn)行該程序如下:

$./ del_msg

------ Message Queues --------

key??????? msqid????? owner????? perms????? used-bytes?? messages???

0x0000007b 0????????? root?????? 666??????? 0??????????? 0??????????

------ Message Queues --------

key??????? msqid????? owner????? perms????? used-bytes?? messages???

successfully removed 0? queue ?

?

?

7.??讀寫消息隊(duì)列

一旦獲得了隊(duì)列標(biāo)識(shí)符,用戶就可以開始在該消息隊(duì)列上執(zhí)行相關(guān)操作了。為了向隊(duì)列

傳遞消息,用戶可以使用?msgsnd系統(tǒng)調(diào)用.

由于消息隊(duì)列的特殊性,系統(tǒng)為這個(gè)數(shù)據(jù)類型提供了兩個(gè)接口(msgsnd函數(shù),msgrcv函數(shù)),分別對(duì)應(yīng)寫消息隊(duì)列及讀消息隊(duì)列。將一個(gè)新的消息寫入隊(duì)列,使用函數(shù)msgsnd,函數(shù)原型如下:

#include <sys/msg.h>

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

對(duì)于寫入隊(duì)列的每一個(gè)消息,都含有三個(gè)值,正長整型的類型字段、數(shù)據(jù)長度字段和實(shí)際數(shù)據(jù)字節(jié)。新的消息總是放在隊(duì)列的尾部,函數(shù)中參數(shù)msqid指定要操作的隊(duì)列,ptr指針指向一個(gè)msgbuf的結(jié)構(gòu),定義如下:

struct msgbuf{

??? long mtype;

??? char mbuf[];

};

這是一個(gè)模板的消息結(jié)構(gòu),其中成員?mbuf是一個(gè)字符數(shù)組,長度是根據(jù)具體的消息來決定的,切忌消息不能以NULL結(jié)尾。成員mtype是消息的類型字段。

函數(shù)參數(shù)nbytes指定了消息的長度,參數(shù)flags指明函數(shù)的行為。函數(shù)成功返回0,失敗返回–1并設(shè)置錯(cuò)誤變量errnoerrno可能出現(xiàn)的值有:EAGAINEACCESEFAULTEIDRMEINTREINVALENOMEM。當(dāng)函數(shù)成功返回后會(huì)更新相應(yīng)隊(duì)列的msqid_ds結(jié)構(gòu)。

使用函數(shù)msgrcv可以從隊(duì)列中讀取消息,函數(shù)原型如下:

#include <sys/msg.h>

ssize_t msgrcv ( int msqid, void *ptr, size_t nbytes, long type , int flag);

函數(shù)中參數(shù)msqid為指定要讀的隊(duì)列,參數(shù)ptr為要接收數(shù)據(jù)的緩沖區(qū),nbytes為要接收數(shù)據(jù)的長度,當(dāng)隊(duì)列中滿足條件的消息長度大于nbytes的值時(shí),則會(huì)參照行為參數(shù)flag的值決定如何操作:當(dāng)flag中設(shè)置了MSG_NOERROR位時(shí),則將消息截短到nbytes指定的長度后返回。如沒有MSG_NOERROR位,則函數(shù)出錯(cuò)返回,并設(shè)置錯(cuò)誤變量errno。設(shè)置type參數(shù)指定msgrcv函數(shù)所要讀取的消息,tyre的取值及相應(yīng)操作如表14-10所示。

14-10? type值詳解

type

????

等于0

返回隊(duì)列最上面的消息(根據(jù)先進(jìn)先出規(guī)則)

大于0

返回消息類型與type相等的第1條消息

小于0

返回消息類型小于等于type絕對(duì)值的最小值的第1條消息

參數(shù)flag定義函數(shù)的行為,如設(shè)置了IPC_NOWAIT位,則當(dāng)隊(duì)列中無符合條件的消息時(shí),函數(shù)出錯(cuò)返回,errno的值為ENOMSG。如沒有設(shè)置IPC_NOWAIT位,則進(jìn)程阻塞直到出現(xiàn)滿足條件的消息出現(xiàn)為止,然后函數(shù)讀取消息返回。

下面實(shí)例演示了消息隊(duì)列在進(jìn)程間的通信。程序中創(chuàng)建了一個(gè)消息的模板結(jié)構(gòu)體,并對(duì)聲明變量做初始化。使用msgget函數(shù)創(chuàng)建了一個(gè)消息隊(duì)列,使用msgsnd函數(shù)向該隊(duì)列中發(fā)送了一條消息。

1)在vi編輯器中編輯該程序如下:

程序清單14-14? snd_msg.c?調(diào)用msgsnd函數(shù)向隊(duì)列中發(fā)送消息

#include <sys/msg.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <stdio.h>

#include <stdlib.h>

struct msg{???????????????????? /*聲明消息結(jié)構(gòu)體*/

??? long msg_types;???????????? /*消息類型成員*/???

??? char msg_buf[511];????????? /*消息*/

};

int main( void ) {

??? int???? qid;

??? int ??????? pid;

??? int ??? ??? len;

??? struct msg pmsg;??????????? /*一個(gè)消息的結(jié)構(gòu)體變量*/

???

??? pmsg.msg_types = getpid();? /*消息類型為當(dāng)前進(jìn)程的ID*/

??? sprintf (pmsg.msg_buf,"hello!this is :%d/n/0", getpid() ); /*初始化消息*/

??? len = strlen ( pmsg.msg_buf );?? /*取得消息長度*/

???

??? if ( (qid=msgget(IPC_PRIVATE, IPC_CREAT | 0666)) < 0 ) {? /*創(chuàng)建一個(gè)消
??? ??????????????????????????????????????????????????????????? ??
息隊(duì)列*/

??????? perror ( "msgget" );

??????? exit (1) ;

??? }

???

??? if ( (msgsnd(qid, &pmsg, len, 0 )) < 0 ){?? /*向消息隊(duì)列中發(fā)送消息*/

??????? perror ( "msgsn" );

??????? exit ( 1 );

??? }

??? printf ("successfully send a message to the queue: %d /n", qid);

??? exit ( 0 ) ;

}

2)在shell中編譯該程序如下:

$gcc snd_msg.c –o snd_msg

3)在shell中運(yùn)行該程序如下:

$./ snd_msg

successfully send a message to the queue 0

上述程序中,先定義了一個(gè)消息的結(jié)構(gòu)體。該結(jié)構(gòu)體中包含兩個(gè)成員,long類型成員msg_types是消息的類型,注意,在消息隊(duì)列中是以消息類型做索引值來進(jìn)行檢索的。char類型數(shù)組存放消息。在程序中先聲明了一個(gè)消息的結(jié)構(gòu)體變量,并做相應(yīng)初始化,然后使用了msgget函數(shù)創(chuàng)建一個(gè)消息隊(duì)列,并將該消息發(fā)送到此消息隊(duì)列中。以下是一個(gè)使用消息隊(duì)列發(fā)送消息的程序。

下面實(shí)例演示了如何使用隊(duì)列讀取消息。在程序的開始部分,判斷用戶是否輸入了目標(biāo)消息隊(duì)列ID,如果沒有,則打印命令的幫助信息;如果用戶輸入了隊(duì)列的ID,則從隊(duì)列中取出該消息,并輸出到標(biāo)準(zhǔn)輸出。

1)在vi編輯器中編輯該程序。

程序清單14-15? rcv_msg.c?使用msgrcv函數(shù)從指定隊(duì)列中讀出消息

#include <sys/msg.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <stdio.h>

#include <stdlib.h>

#define BUFSZ 4096

struct msg{???????????? /*聲明消息結(jié)構(gòu)體*/

??? long msg_types;???? /*消息類型成員*/???

??? char msg_buf[511];? /*消息*/

};

int main( int argc, char * argv[] ) {

??? int???? qid;

??? int ??????? len;

??? struct msg pmsg;

??? if ( argc != 2 ){? /**/

??????? perror ( "USAGE: read_msg <queue ID>" );

??????? exit ( 1 );

??? }

???

??? qid = atoi ( argv[1] );?? /*從命令行中獲得消息隊(duì)列的ID*/

??? /*從指定隊(duì)列讀取消息?*/

??? len = msgrcv ( qid, &pmsg, BUFSZ, 0, 0 );

???

??? if ( len > 0 ){

??????? pmsg.msg_buf[len] = '/0';?????????????????????? /*為消息添加結(jié)束符*/

??????? printf ("reading queue id :%05ld/n", qid ); /*輸出隊(duì)列ID*/

??????? /*該消息類型就是發(fā)送消息的進(jìn)程ID*/

??????? printf ("message type : %05ld/n", pmsg.msg_types );

??????? printf ("message length : %d bytes/n", len );?? /*消息長度*/

??????? printf ("mesage text: %s/n", pmsg.msg_buf); /*消息內(nèi)容*/

??? }

??? else if ( len == 0 )

??????? printf ("have no message from queue %d/n", qid );

??? else {

??????? perror ( "msgrcv");

??????? exit (1);

??? }

??? system("ipcs -q")??

??? exit ( 0 ) ;

}

2)在shell中編譯該程序如下:

$gcc rcv_msg.c–o rcv _msg

3)在shell中運(yùn)行該程序如下:

$./ rcv_msg 0

reading queue id :0

message type : 03662

message length : 20 bytes

mesage text: hello!this is :3662

------ Message Queues --------

key??????? ??msqid????? owner????? perms????? used-bytes?? messages???

0x00000000 ?0????????? root?????? ?666??????? ?0??????????? 0??????????

該程序中聲明了一個(gè)消息的結(jié)構(gòu)體類型變量,并從命令行中得到所要操作的消息隊(duì)列,然后使用函數(shù)msgrcv從指定消息隊(duì)列中讀取隊(duì)列中最上面的一條消息(函數(shù)的第4個(gè)參數(shù)等于0,說明根據(jù)先進(jìn)先出規(guī)則,應(yīng)從隊(duì)列的最上面讀取一條消息),并將該消息輸出到標(biāo)準(zhǔn)輸出。在發(fā)送消息的程序中,消息類型字段指定的是發(fā)送消息進(jìn)程的ID,可以使用該內(nèi)容來判斷信息的來源。



總結(jié)

以上是生活随笔為你收集整理的Linux进程间通讯之消息队列的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。