消息队列也是一种用于进程间通信的方式,它放在计算机内核中,并由消息队列表示符(类比文件描述符)标识,它由操作系统维护。
消息队列的特点:
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 全部