进程间通信(2)消息队列

来源:互联网 发布:用友政务软件报价 编辑:程序博客网 时间:2024/05/11 20:15

消息队列也是一种用于进程间通信的方式,它放在计算机内核中,并由消息队列表示符(类比文件描述符)标识,它由操作系统维护。

消息队列的特点:

1>它支持进程间双向无阻塞的通信。

2>它是面向消息传递的。

3>它的生命周期是随计算机内核的。

下图列出了消息队列的最大消息的一些数据。

wKioL1cLoKHwIIQaAAFjL6kb1TM351.png

在创建一个消息队列时需要这几个函数:

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与其关联

wKiom1cLnWrQkeh2AAHNQ9Vxa0c858.png

上面的一个数据结构就是消息队列所维护的结构体,而下面那个结构体则是每一个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

0 0