3、SystemV 消息队列

来源:互联网 发布:淘宝买家恶意大量退货 编辑:程序博客网 时间:2024/05/21 14:54
3、SystemV 消息队列
为了便于进程之间通信,我们可以使用管道通信 SystemV 也提供了一些函数来实现进程的
通信.这就是消息队列.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key,int msgflg);
34
int msgsnd(int msgid,struct msgbuf *msgp,int msgsz,int msgflg);
int msgrcv(int msgid,struct msgbuf *msgp,int msgsz,
long msgtype,int msgflg);
int msgctl(Int msgid,int cmd,struct msqid_ds *buf);
struct msgbuf
{
long msgtype; /* 消息类型 */
....... /* 其他数据类型 */
}
msgget 函数和semget 一样,返回一个消息队列的标志.msgctl 和semctl 是对消息进行控
制.. msgsnd 和msgrcv 函数是用来进行消息通讯的.msgid 是接受或者发送的消息队列标
志.msgp 是接受或者发送的内容.msgsz 是消息的大小. 结构msgbuf 包含的内容是至少有
一个为msgtype.其他的成分是用户定义的.对于发送函数msgflg 指出缓冲区用完时候的操
作.接受函数指出无消息时候的处理.一般为0. 接收函数msgtype 指出接收消息时候的操作.
如果msgtype=0,接收消息队列的第一个消息.大于0 接收队列中消息类型等于这个值的第
一个消息.小于0 接收消息队列中小于或者等于msgtype 绝对值的所有消息中的最小一个消
息. 我们以一个实例来解释进程通信.下面这个程序有server 和client 组成.先运行服务
端后运行客户端.服务端 server.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/msg.h>
#define MSG_FILE "server.c"
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype
{
long mtype;
char buffer[BUFFER+1];
};
int main()
{
struct msgtype msg;
key_t key;
int msgid;
if((key=ftok(MSG_FILE,'a'))==-1)
{
fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
35
exit(1);
}
if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)
{
fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
exit(1);
}
while(1)
{
msgrcv(msgid,&msg,sizeof(struct msgtype),1,0);
fprintf(stderr,"Server Receive:%s\n",msg.buffer);
msg.mtype=2;
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
}
exit(0);
}
客户端(client.c)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#define MSG_FILE "server.c"
#define BUFFER 255
#define PERM S_IRUSR|S_IWUSR
struct msgtype
{
long mtype;
char buffer[BUFFER+1];
};
int main(int argc,char **argv)
{
struct msgtype msg;
key_t key;
int msgid;
if(argc!=2)
{
fprintf(stderr,"Usage:%s string\n\a",argv[0]);
exit(1);
}
if((key=ftok(MSG_FILE,'a'))==-1)
36
{
fprintf(stderr,"Creat Key Error:%s\a\n",strerror(errno));
exit(1);
}
if((msgid=msgget(key,PERM))==-1)
{
fprintf(stderr,"Creat Message Error:%s\a\n",strerror(errno));
exit(1);
}
msg.mtype=1;
strncpy(msg.buffer,argv[1],BUFFER);
msgsnd(msgid,&msg,sizeof(struct msgtype),0);
memset(&msg,'\0',sizeof(struct msgtype));
msgrcv(msgid,&msg,sizeof(struct msgtype),2,0);
fprintf(stderr,"Client receive:%s\n",msg.buffer);
exit(0);
}

注意服务端创建的消息队列最后没有删除,我们要使用ipcrm 命令来删除的.

ipcs

ipcrm -q msqid