进程通信之消息队列

来源:互联网 发布:程序员高清图 编辑:程序博客网 时间:2024/06/05 17:56

1。消息队列
消息队列提供一种从一个进程到另一个进程发送有类型数据块的方法。消息队列与管道的不同是消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定先进先出,与命名管道有一样的不足就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数也是有上限的(MSGMNB),系统上消息队列的总数也是有上限的(MSGMNI)
2.函数:
(1)创建消息队列或取到已存在的消息队列
int msgget(key_t key,int msgflg)
key:可以用函数ftok函数产生(ftok把一个已经存在的路径名和一个整数标识转换为一个key_t值,称为IPC键)
msgflg:
IPC_CREAT:如果IPC不存在则创建一个,并返回标识,存在则打开
IPC_EXCL:只有IPC不存在时,新建IPC才建立,否则产生错误,本身 并没多大意义,和IPC_CREAT一起使用
一般IPC_EXCL 和IPC_CREAT一起使用,XXget()将返回一个新建IPC标识,存在则返回-1;
(2)向消息队列读写
从消息队列读:
ssize_t msgrcv(int msgqid,void * msgp,size_t msgsz,long msgtyp ,int msgflg)
从消息队列写
int msgsnd(int msgqid,const void * msgp,size_t msgsz ,int msgflg)
msgp:指向消息缓冲的指针,此位置用来暂时存储发送和接受的消息,是用户可定义的通用结构,形态如下
struct msgstru{
long mtype;
char mtext[];
}
msgsz:消息的大小
msgtyp:从消息队列读取消息的形态
msgflg:用来指明核心程序在队列没有数据的情况应采取的行动,如:
msgflg=0,以阻塞方式等待 ,
如果和IPC_NOWAIT合用,msgsnd()消息队列已满,不会阻塞,而是立即返回-1,msgrcv(),消息队列空时,不等待返回-1,并返回错误码ENOMSG
(3)设置消息队列属性
int msgctl(int msgqid,int cmd,struct msgqid_ds*buf)
msgctl系统调用对msgqid标识执行cmd操作
cmd操作:
IPC_STAT:用来获取消息队列对应的migqid_ds数据结构,并将其保存在buf指定的空间
IPC_SET:设置消息队列属性,要设置的属性存放在buf中
IPC_RMID:从内核中删除msgqip标识的消息队列
commen.c代码:`#include “queue.h”
int comMsgQue(int flg)
{
key_t key=ftok(“.”,0X666);
if(key<0)
return -2;

int id= msgget(key,flg);if(id<0){    perror("msg");    return -1;}else    return id;

}
int creatMsgQue()
{

return comMsgQue(IPC_CREAT|IPC_EXCL|0666);

}
int getMsgQue()
{

return  comMsgQue(IPC_CREAT);

}
int sendMsg(int msg_id ,long type, const char*infor)
{
struct msgbuf msg;
msg.msgtype=type;
strcpy ( msg.msgtext,infor);
return msgsnd(msg_id,&msg,sizeof(msg.msgtext),0);
}
int recvMsg(int msg_id,long type , char out[])
{
struct msgbuf msg;
msg.msgtype=type;
int r=msgrcv(msg_id,&msg,sizeof(msg.msgtext),type,0);
strcpy(out,msg.msgtext);
return r;

}
int destoryMsgQue(int msg_id)
{
return msgctl(msg_id,IPC_RMID,NULL);
}
`
代码queue.h

#ifndef _QUEUE_H_#define _QUEUE_H_#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>#include<stdio.h>#include<unistd.h>#include<string.h>#define SERVER 1#define CLIENT 2int creatMsgQue();int getMsgQue();int sendMsg(int msg_id,long type,const char*_info);int destoryMsgQue(int msg_id);int recvMsg(int msg_id,long type,char out[]);struct msgbuf{    long msgtype;    char  msgtext[128];};#endif

server.c的代码

#include "queue.h"int main(){    int queid=creatMsgQue();    printf("%d\n",queid);    char out[128];    while(1)    {      recvMsg(queid,CLIENT,out);        printf("client:%s",out);    printf("please enter:");    fflush(stdout);     ssize_t  s=read(0,out,sizeof(out)-1);         if(s>0)         {out[s-1]='\0';        sendMsg(queid,SERVER,out);           }    }  destoryMsgQue(queid);        return 0;}

client.c的代码

#include "queue.h"int main(){//  struct msgbuf msg;    int queid=getMsgQue();    printf("%d\n",queid);    char buff[128];    while(1)    {        printf("please enter:");    fflush(stdout);     ssize_t  s=read(0,buff,sizeof(buff)-1);         if(s>0)      { buff[s-1]='\0';        sendMsg(queid,CLIENT,buff);  }     recvMsg(queid,SERVER,buff);        printf("from server:%s\n",buff);    }  //destoryMsgQue(queid);        return 0;}
0 0