您的位置:首页 > 运维架构 > Linux

linux进程通信之消息队列

2017-09-15 16:39 447 查看
进程通信信号量方式传送信息量有限,管道只能传送无格式字节流,无疑给程序开发带来不便,消息队列克服了这些缺点。

消息队列就是一个消息链表,可以把消息看做一个记录,具有特定格式,进程可以向其中按照一定规则添加新消息;另一些进程可以从消息队列读走消息。

消息队列只有在内核重新启动,或者人工删除才会消失。消息队列内核持续性需要消息队列在系统范围内拥有唯一个键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值。

键值函数结构如下:

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(char *pathname,char proj);
功能:

返回文件名对应的键值

pathname:文件名

proj:项目名不为0即可

打开消息队列函数结构:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key,int msgflg);
功能:

返回值:与键值对应的消息队列描述字

key:键值,有ftok获得。

msgflg:标志位

常用标志位:

IPC_CREAT

创建新的消息队列

IPC_EXCL

与IPC_CREAT一同使用,表示如果创建的消息队列已经存在,返回错误。

IPC_NOWAIT

读写消息队列无法满足要求时不阻塞。

以下两种情况将创建消息队列:

1)没有与键值对应的消息队列,并且msgflg有IPC_CREAT参数。

2)key参数为IPC_PRIVATE。

发送消息函数结构:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sysmsg.h>
int megsend(int msgid,struct msgbuf *msgp,int msgsz,int msgflg);
功能:

向消息队列发送一条消息

msgqid 消息队列描述字。

msgp 存放消息结构。

msgsz 消息数据的长度。

msgflag 发送标志  有意义的发送标志为IPC_NOWAIT,指明在消息队列乜有足够空间容纳要发送的消息时,是否等待。

消息格式

struct msgbuf

{

long type  //消息类型  >0

char ext[1]  //消息数据的首地址  

}

接收消息函数结构如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msgid,struct msgbuf*msgp,int msgsz,long msgtpy,int msgflg);
功能:

从msgid代表的队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中,再成功读取一条消息后,消息队列中这条消息将被删除。

多说无益直接上代码:

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

struct msg_buf
{
int mtype;
char data[255];
};

int main()
{
key_t key; //消息队列键值
int msgid; //消息队列描述符
int ret;
struct msg_buf msgbuf; //消息队列结构

key=ftok("/tmp/2",'a'); //创建消息队列 获取键值
printf("key =[%x]\n",key); //打印键值
msgid=msgget(key,IPC_CREAT|0666); /*通过文件对应*/

if(msgid==-1)
{
printf("create error\n");
return -1;
}

msgbuf.mtype = getpid(); //消息编号为自身进程ID (只要大于0就可以)
strcpy(msgbuf.data,"this is a message");
ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT); //向消息队列发送 编号为自身ID 内容为 this is a message的消息
if(ret==-1)
{
printf("send message err\n");
return -1;
}

memset(&msgbuf,0,sizeof(msgbuf)); //清空消息队列为接收做准备
ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);//接收消息队列中编号为自身进程ID的消息
if(ret==-1)
{
printf("recv message err\n");
return -1;
}
printf("recv msg =[%s]\n",msgbuf.data); //打印接受的消息

}执行代码查看运行状况:
[root@localhost mesg]# ls
msg msg.c
[root@localhost mesg]# ./msg
key =[ffffffff]
recv msg =[this is a message]
[root@localhost mesg]# 在运行结果中可以看到在消息队列中读取到了编号为当前进程id的消息“”this is a message“”
这就是最简单的消息队列演示。





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息