首页 > 代码库 > LInux进程间通信之消息队列编程实例

LInux进程间通信之消息队列编程实例

  本文主要通过消息队列的编程实例来加深对消息队列的理解.

一、消息队列之创建

  创建一个消息队列,需要用到一个函数:

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>

int msgget(key_t key,int msgflg);

   key:需要调用ftok函数来获取.

  msgflg:IPC_CREAT,不存在则创建,存在则返回已有的qid.

     IPC_CREAT|IPC_EXCL,不存在则创建,存在则返回出错.

  ftok函数原型如下:

#include<sys/types.h>
#include<sys/ipc.h>

key_t ftok(const char*pathname,int proj_id);

   ftok函数通过给定的路径名称取得其stat结构中的st_dev字段和st_info字段,然后将它们和项目id结合起来,然后产生一个键返回.

  为了方便使用,我们将创建消息队列与获取消息队列封装为两个函数:

//创建与打开消息队列公共函数
int MessageCommon(key_t key,int flag){
	int ret = 0;
	if((ret=msgget(key,flag))==-1){
		perror("msgget:");
		exit(-1);
	}
	return ret;
}
//创建全新的消息队列(服务端)
int CreateMessage(key_t qid){
        //消息队列也是具有权限结构的,因此在创建时给666权限
	return MessageCommon(qid,IPC_CREAT|IPC_EXCL|0666);
}
//打开已有的消息队列(客户端)
int GetMessage(key_t qid){
	return MessageCommon(qid,IPC_CREAT);
}

二、消息队列之发送消息

  使用消息队列发送消息用到了一个函数和一个结构体:

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>

int msgsnd(int msgid,const void* msgp,size_t magsz,int msgflg);

   msgid:消息队列标识符

  msgp:发送的消息结构体指针

  msgsz:结构体中消息的大小(不是整个结构体的大小)

  msgflg:IPC_NOWAIT,消息队列满时返回-1

     0,消息队列满时阻塞.

  在通过msgsnd发送数据时,需要一个结构体来存放所发送的数据,及发送者的类型.

struct msgbuf{
        long mtype;        //消息类型,由用户自定义
        char mtext[1024];//发送的消息(长度、类型可以自行指定)
}

   因此,我们将发送消息也做一层封装:

//发送消息
void SendMessage(int msgid,const char* msg,int who){
	msgbuf buf;
	buf.mtype = who;                //消息类型
	strcpy(buf.mtext,msg);        //消息内容
	if(msgsnd(msgid,&buf,sizeof(buf.mtext),0) == -1){
		perror("msgsnd");
		DestoryMessage(msgid);
		exit(-2);
	}
}

 三、消息队列之接收消息

  消息队列接收消息的函数原型如下:

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>

ssize_t msgrcv(int qid,void *msgp,size_t msgsz,long msgtyp,int msgflg);

   qid:消息队列的标识符

  msgp:消息结构体指针

  msgsz:消息内容大小

  msgtyp:消息类型

  msgflg:同上

  封装之后的代码如下:

void ReceiveMessage(int msgid,char* msg,int who){
	msgbuf buf;
	if(msgrcv(msgid,&buf,sizeof(buf.mtext),who,0)==-1){
		perror("msgrcv");
		DestoryMessage(msgid);
		exit(-3);
	}
	strcpy(msg,buf.mtext);
}

四、消息队列的删除

  其函数原型如下:

#include<sys/type.h>
#include<sys/ipc.h>
#Include<sys/msg.h>

int msgctl(int msgid,int cmd,struct msgid_ds *buf);

  msgid:消息队列标识符

  cmd:所要采取的命令.IPC_RMID删除消息队列

  buf:权限信息

  封装后函数如下:

//消息队列的删除
void DestoryMessage(int msgid){
	if(msgctl(msgid,IPC_RMID,NULL) == -1){
		perror("msgctl");
		exit(-4);
	}
}

   以上便是消息队列的基本操作,关于消息队列通信实例为节省文章篇幅,请移步至:https://github.com/gaoxiaodiao/Linux/tree/master/LinuxCode/MessageQueue

LInux进程间通信之消息队列编程实例