消息隊列也是一種用於進程間通信的方式,它放在計算機內核中,並由消息隊列表示符(類比文件描述符)標識,它由操作系統維護。
消息隊列的特點:
1>它支持進程間雙向無阻塞的通信。
2>它是面向消息傳遞的。
3>它的生命週期是隨計算機內核的。
下圖列出了消息隊列的最大消息的一些數據。
在創建一個消息隊列時需要這幾個函數:
int msgget(key_t key, int msgflg);
key:由ftok函數創建
msgflg:有ICP_CREAT和ICP_ECXL兩個宏參數,第一個參數爲新創建一個如果系統中有則返回這個id,第二個參數一般和第一個組合使用爲了新創建一個。
key_t ftok(const char *pathname, int proj_id);
該函數第一個參數是指定的路徑,第二個參數可由用戶自定義一個數,返回一個由這個參數組成的一個數。
每個隊列創建好都有一個 msqid_ds與其關聯
上面的一個數據結構就是消息隊列所維護的結構體,而下面那個結構體則是每一個IPC都要維護的一個結構。
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl是用於在消息隊列結束時做的一些工作,第二個參數cmd會有一些不同的宏參數來讓它執行不同的功能。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd用於發送消息,msgp是一個結構體,原型如下:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
msgbuf中的mtype是用於標識接受的是來自誰的消息或者是誰發送的消息,mtext則適用於存放消息的數組了。
msgflg用於指定消息以什麼方式傳輸---IPC_NOWAIT(消息已滿會返回錯誤,類似於非阻塞傳輸),如果沒有設置或設置爲零則以阻塞方式發送,
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgtyp>0時返回以msgtyp標識的第一條消息
msgtyp==0時返回消息隊列中的第一條消息
msgtyp<小於0時返回絕對值等於msgtyp標識的消息若消息有若干個則返回類型最小的消息
下面是一個簡單的阻塞方式的消息隊列;
.h
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/types.h>
4 #include<sys/ipc.h>
5 #include<sys/msg.h>
6 #include<string.h>
7
8 #define _PATH_ "."
9 #define _PROJECT_ID_ 0x6666
10 #define _MAX_BUF_ 1024
11 #define _SERVER_ID_ 1
12 #define _CLIENT_ID_ 2
13
14 typedef struct msgvp
15 {
16 long mtype;
17 char mmsg_buf[_MAX_BUF_];
18 }msgvp;
19 static int comm_msgget(int flag)
20 {
21 key_t key=ftok(_PATH_,_PROJECT_ID_);
22 if(ftok<0)
23 {
24 perror("ftok");
25 exit(1);
26 }
27 int msg_id=msgget(key,flag);
28 if(msg_id<0)
29 {
30 perror("msg_id");
31 exit(1);
32 }
33 return msg_id;
34 }
35
36 int get_msgid()
37 {
38 umask(0);
39 int msg_id=comm_msgget(IPC_CREAT|IPC_EXCL|0666);
40 return msg_id;
41 }
42
43 int use_msgid()
44 {
45 int msg_id=comm_msgget(IPC_CREAT);
46 return msg_id;
47 }
48
49 void msg_receive(int msg_id,msgvp*msg_vp,int msgvp_size,long mstype)
50 {
51 memset(msg_vp->mmsg_buf,'\0',sizeof(msg_vp->mmsg_buf));
52 if(msgrcv(msg_id,msg_vp,msgvp_size,mstype,0)<0)
53 {
54 perror("msgsve");
55 }
56 }
57
58 void msg_send(int msg_id,msgvp*msg_vp,int msgvp_size,char *str,int msgtype)
59 {
60 memset(msg_vp->mmsg_buf,'\0',sizeof(msg_vp->mmsg_buf));
61 strcpy(msg_vp->mmsg_buf,str);
62 msg_vp->mtype=msgtype;
63 if(msgsnd(msg_id,msg_vp,msgvp_size,0)<0)
64 {
65 perror("msgsnd");
66 }
67 }
68
69 void msg_distory(int msg_id)
70 {
71 if(msgctl(msg_id,IPC_RMID,0)<0)
72 {
73 perror("msgctl");
74 }
75 }
server.c
1 #include"comm.h"
2
3
4 int main()
5 {
6 int msg_id=get_msgid();
7 msgvp serve;
8 char my_buf[_MAX_BUF_];
9 while(1)
10 {
11 sleep(5);
12 msg_receive(msg_id,&serve,sizeof(serve),_CLIENT_ID_);
13 printf("client:%s",serve.mmsg_buf);
14
15 printf("please write to client:");
16 fflush(stdout);
17 int size=read(0,my_buf,_MAX_BUF_);
18 if(size>0)
19 {
20 my_buf[size]='\0';
21 }
22 msg_send(msg_id,&serve,sizeof(serve),my_buf,_SERVER_ID_);
23 }
24
25 msg_tory();
26 return 0;
27 }
~
"server.c" 27L, 443C 1,16 全部
client.c
1
2 #include"comm.h"
3
4
5 int main()
6 {
7 int msg_id=use_msgid();
8 msgvp client;
9 char my_buf[_MAX_BUF_];
10 while(1)
11 {
12 printf("please write to server:");
13 fflush(stdout);
14 int size=read(0,my_buf,_MAX_BUF_);
15 if(size>0)
16 {
17 my_buf[size]='\0';
18 }
19 msg_send(msg_id,&client,sizeof(client),my_buf,_CLIENT_ID_);
20
21
22 sleep(5);
23 msg_receive(msg_id,&client,sizeof(client),_SERVER_ID_);
24 printf("server:%s",client.mmsg_buf);
25
26 }
27 return 0;
28 }
"client.c" 28L, 441C 1,0-1 全部
本文出自 “痕跡” 博客,請務必保留此出處http://wpfbcr.blog.51cto.com/10696766/1762765