您的位置:首页 > 其它

IPC-消息队列

2017-06-18 19:26 176 查看

消息队列

消息队列是消息的链式队列,提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都有一个特定的类型,接收者进程接受的数据块可以有不同的类型值。

特点

依赖于操作系统的IPC模块

可以进行进程间的双向通信

消息队列是基于消息的,管道是基于字节流的

消息队列不一定是先入先出

消息队列的每个消息的长度是有上限的,总的字节数是有上限的,系统的上消息队列的总数有上限。

消息队列的两种数据结构

msqid_ds:标识整个消息队列的基本情况,主要包括整个消息队列的权限,拥有者和操作权限。还有两个指针分别指向消息队列的第一个消息和最后一个消息。

msg:整个数据队列的主体,一个消息队列有若干个消息,每个消息队列的属性有消息类型,消息大小,消息内容指针和下一个消息数据结构的位置。

消息队列模型



消息队列管理函数

创建消息队列

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

int msgget(key_t key, int msgflg);
//创建新消息队列或取得已存在的消息队列
第一个参数key是有ftork()创建的。第二个参数msgflg的对位用来确定消息队列的访问权限
If  msgflg  specifies  both  IPC_CREAT and IPC_EXCL and a message queue
already exists for key, then msgget() fails with errno set  to  EEXIST.
(This  is  analogous  to the effect of the combination O_CREAT | O_EXCL
for open(2).)
//IPC_CREAT:如果ipc不存在就创建一个,否则就打开
//IPC_EXCL:如果key存在,就返回失败
//如果将IPC_SREAT和IPC_EXCL标志一起使用,新建一个ipc资源,如果存在则返回-1


2.消息队列属性控制

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
//创建消息队列后,对消息队列的属性进行修改
//msqid消息队列的标识符,是使用msgget的返回值
//cmd要执行的操作
//3种cmd操作.IPC_STAT该命令用来获取消息队列的msqid_ds数据结构,并将其保存在buf指向的结构中。IPC_SET该命令用来设置消息队列的属性,要设置的属性保存在buf中。IPC_RMID:从内核中删除msqid


3.向队列中读写消息

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//将新的消息添加到消息队列尾端。
//参数msqid为msgget的返回值,
//msgp为指向的用户定义的缓冲区
struct msgbuf {
long mtype;//消息类型
char mtext[1]; //消息内容
};
//msgsz为接受消息的大小
//msgflg用来指定在到达系统为消息队列所定的界限(如达到的字数限制)时应采取的操作。如果设置为IPC_NOWAIT,如果执行的是msgsnd()消息队列满时,不会阻塞,立即返回-1。如果执行的是msgrcv,消息队列为空是,立即返回并设置错误码是ENOMSG。

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
//用于从队列中取消息。
//msqid表示从哪个消息队列中取消息
//msgp一个临时消息的数据结构,用来保存读取的消息
struct msgbuf {

long mtype;//消息类型

char mtext[1]; //存储消息位置,需要重新定义

};

//msgsz用于指定mtext的大小
//msgtyp用于指定请求消息的类型,=0收到队列的第一条消息,任意类型;>0收到第一条msgtyp类型的消息;<0收到第一条最低类型(小于或等于msgtyp的绝对值)的消息
//msgflg用来指定在到达系统为消息队列所定的界限(如达到的字数限制)时应采取的操作。如果设置为IPC_NOWAIT,如果执行的是msgsnd()消息队列满时,不会阻塞,立即返回-1。如果执行的是msgrcv,消息队列为空是,立即返回并设置错误码是ENOMSG


代码实现

//msg_receiver.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
struct data
{
long msg_type;
char msg_text[512];
};
int main()
{
int msgid;
struct data msg_data;

if(msgid=msgget((key_t)1234,0666|IPC_CREAT)==-1)
{
perror("msgget");
return 1;
}
while(1)
{
if(msgrcv(msgid,&msg_data,512,(long)0,0)==-1)
{
perror("msgrcv");
return 2;
}
printf("A receive:%s\n",msg_data.msg_text);
printf("A send");
memset(msg_data.msg_text,0,sizeof(msg_data.msg_text));
fgets(msg_data.msg_text,512,stdin);
if(msgsnd(msgid,&msg_data,512,0)==-1)
{
perror("msgsnd");
return 3;
}
if(strncmp(msg_data.msg_text,"end",3)==0)
{
printf("A  end\n");
break;
}
}
if(msgctl(msgid,IPC_RMID,0)==-1)
{
perror("msgctl");
return 4;
}
return 0;
}


//msg_sender.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#define MAX_TEXT 512
struct data
{
long my_msg_type;
char msg_text[MAX_TEXT];

};
int main()
{
struct data some_data;
int msgid;
key_t key=ftok(".",88);
if(msgid=msgget(key,0666|IPC_CREAT)==-1)
{

return 1;
}

while(1)
{
printf("B send:");
fgets(some_data.msg_text,512,stdin);

if(msgsnd(msgid,&some_data,MAX_TEXT,0)==-1)
{
perror("msgsnd");
return 2;

}
if(strncmp(some_data.msg_text,"end",3)==0)
{

break;
}
memset(some_data.msg_text,0,sizeof(some_data.msg_text));
if(msgrcv(msgid,&some_data,MAX_TEXT,(long)0,0)==-1)
{
perror("msgrcv");
return 3;
}
printf("B receive:%s\n",some_data.msg_text);
if(strncmp(some_data.msg_text,"end",3==0))
{
printf("B end");
break;
}

}

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