一.消息队列先知
其实,消息队列与命名管道有很多相似之处,但少了在打开和关闭管道方面的复杂性。但使用消息队列应为解决我们在,命名管道时遇到的一些问题,比如管道的阻塞问题。
消息队列提供了一种子啊两个不想管的进程之间传递数据的相当简单且有效的方法,与命名管道相比,消息队列的优势在于,它独立于发送和接收进程而存在。
消息队列提供了一种从一个进程想另一个进程发送一个数据块的方法。每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型值的数据块。但是,这些数据块都有一个最大长度的先知,系统中所有队列所包含的全部数据块的长度也有一个上限。
二.消息队列有关的函数
消息队列函数都包含在一个头文件中:
#include<sys/msg.h>
创建和访问一个消息队列的函数msgget()
int msgget(key_t key,int msgflg)
//第一个参数key,通过这个键值来命名某个特定的消息队列
//第二个参数msgflg,由9个权限标志组成
//由IPC_CREATE定义的一个特殊位必须和权限标志位或才能创建一个新的消息队列
把消息添加到消息队列的函数msgsnd()
int msgsnd(int msqid,const void *msg_ptr,size_t msg_sz,int msgflg)
//第一个参数msqid,是由msgget函数返回的消息队列标识符
//第二个参数msg_ptr,是一个指向准备发送消息的指针
//第三个参数msg_sz,是msg_ptr指向的消息的长度
//第四个参数msgsnd,控制在当前消息队列满或队列消息到达系统范围的限制时将要发生的事情
从一个消息队列中获取消息的函数msgrcv()
int msgrcv(int msqid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg)
//第一个参数msqid,是由msgget函数返回的消息队列标识符
//第二个参数msg_ptr,是一个指向准备接受消息的指针
//第三个指针msg_sz,是msg_ptr指向的消息的长度
//第四个参数msgtype,实现一种简单形式的接收优先级
//第五个参数msgflg,用于控制当前队列中没有响应类型的消息可以接收时将发生的事情
消息队列的控制函数msgctl()
int msgctl(int msgid,int command,struct msgid_ds *buf)
//第一个参数msgid,是由mdsgget返回的消息队列标识符
//第二个参数command,是将要采取的动作
//第三个参数是一个结构体
结构体内容如下:
struct msgid_ds{
uid_t msg_perm.uid;
uid_t msg_perm.gid;
uid_t msg_perm.mode;
};
三.源码实现
main.c//向消息队列内存写入
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/msg.h>
struct mess
{
long type;
char buff[128];
};
int main()
{
int msgid = msgget((key_t)1357,IPC_CREAT|0666);
assert(msgid != -1);
struct mess dt;
dt.type = 2;
strcpy(dt.buff,"i am zkr");
//int i = 1;
//for(;i<65536;i++)
//{
msgsnd(msgid,(void*)&dt,128,0);//这里的大小只是数据的大小
//printf("i = %d\n",i);
//}
}
test.c//打印main.c里边的内容
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/msg.h>
struct mess
{
long type;
char buff[128];
};
int main()
{
int msgid = msgget((key_t)1357,IPC_CREAT|0666);
assert(msgid != -1);
struct mess dt;
dt.type = 2;
strcpy(dt.buff,"i am zkr");
msgrcv(msgid,(void*)&dt,128,0,0);
printf("dt.buff = %s\n",dt.buff);
}
四.结果展示
这里补充个小知识:
我们可以利用命令ipcs -q查看消息队列
如果在没有创建消息队列之前,应该是这样的:
运行完程序再查看应该是这样的:
其实到现在我们可以看出,消息队列的创建是在程序之外的,换而言之,就是说消息队列创建完成之后并不会因为程序结束被释放空间。那么,我们可以用ipcrm -q +msqid 命令来删除消息队列,如下: