消息队列的特点:
1. 消息队列可以实现消息的随机查询,满足队列的特点但不一定要以先进先出的次序读取,可以按消息的类型读取;
2.消息队列允许一个或多个进程向它写入或者读取消息;
3.与无名管道、有名管道一样,从消息队列中读出消息,消息队列中数据会被删除;
4.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级;
5. 只有内核重启或人工删除时,该消息才会被删除,若不人工删除消息队列,消息队列会一直存在于内存中。
消息队列标识符,来标识消息队列。消息队列在整个 系统中是唯一的。
在Linux操作系统中消息队列限制值如下:
1. 消息队列个数最多为16个
2. 消息队列总容量最多为16384字节
3.每个消息内容最多为8192字节
System V提供的IPC通信机制需要一个key值,通过key 值就可在系统内获得一个唯一的消息队列。
key值可以是人为指定的,也可以通过ftok函数获得。
/*
//1.创建消息队列
int msgget(key_t key, int msgflg);
msgflg: 标识函数的行为及消息队列的权限,其取值如下
'IPC_CREAT':创建消息队列。
'IPC_EXCL': 检测消息队列是否存在。
位或权限位:消息队列位或权限位后可以设置消息队列的访问权限,但可执行权限未使用。一般是0666
返回值: 成功返回消息队列的标识符 ;失败返回
//2.写入消息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgflg:函数的控制属性,其取值如下:
'0': msgsnd()调用阻塞直到条件满足为止。
'IPC_NOWAIT': 若消息没有立即发送则调用该函数的进程会立即返回。
返回值:成功返回0,失败返回-1。
//3.读取消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgtyp:消息的类型:
msgtyp = 0:返回队列中的第一个消息。
msgtyp > 0:返回队列中消息类型为 msgtyp 的消息(常用)。
msgtyp < 0:返回队列中消息类型值小于或等于 msgtyp 绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。在获取某类型消息的时候,若队列中有多条 此类型的消息,则获取最先添加的消息,即先进先出原则。
msgflg:函数的控制属性:
'0': msgrcv() 调用阻塞直到接收消息成功为止。
'MSG_NOERROR': 若返回的消息字节数比 nbytes 字节数多,则消息就会截短到 nbytes 字节,且不通知消息发送进程。
IPC_NOWAIT: 调用进程会立即返回。若没有收到消息则立即返回 -1。
返回值: 成功读取消息的长度; 失败:-1
//4.消息队列控制
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd::
'IPC_RMID' :删除消息队列。从系统中删除给消息队列以及仍在该队列上的所有数据,这种删除立即生效。仍在使用这一消息\
队列的其他进程在它们下一次试图对此队列进行操作时,将出错,并返回EIDRM。 此命令只能由如下两种进程执行:
1.其有效用户ID等于msg_perm.cuid或msg_perm.guid的进程。
2.另一种是具有超级用户特权的进程。
'IPC_SET' :设置消息队列的属性。按照buf指向的结构中的值,来设置此队列的msqid_id结构。该命令的执行特权与上一个相同。
'IPC_STAT':读取消息队列的属性。取得此队列的msqid_ds结构,并存放在buf*中。
'IPC_INFO':读取消息队列基本情况。
buf:队列中的内容,一般为NULL。
*/
/*msg_send.c*/
#include
#include
#include
#include
#include
struct msgbuf{
long mtype;//消息类型(>0)
char mtext[128];//消息文本
};
int main()
{
key_t key;
struct msgbuf send = {888,"this message from send"};
struct msgbuf getbuf;
//获取key值
//key_t ftok(const char *pathname, int proj_id);
key = ftok(".",'z');// 路径 id号
if(key == -1){
printf("ftok error\n");
}
printf("key:%x\n",key);
//创建消息队列
int msqid = msgget(key,IPC_CREAT|0666);
if(msqid == -1){
printf("msg creat failed\n");
}
//将消息类型为'888'的信息写入队列,'0'以阻塞的方式写入
if( msgsnd(msqid,&send,strlen(send.mtext),0) == -1){
printf("msgsend error\n");
}
//从队列中读取消息类型为'666'的信息,'0',以阻塞的方式读
msgrcv(msqid,&getbuf,128,666,0);
printf("%s\n",getbuf.mtext);
//删除队列
msgctl(msqid,IPC_RMID,NULL);
return 0;
}
/*msg_get.c*/
#include
#include
#include
#include
#include
struct msgbuf{
long mtype;//消息类型(>0)
char mtext[128];//消息文本
};
int main()
{
key_t key;
struct msgbuf send = {666,"this message from get"};
struct msgbuf getbuf;
key = ftok(".",'z');
if(key == -1){
printf("ftok error\n");
}
printf("key:%x\n",key);
//创建消息队列
int msqid = msgget(key,IPC_CREAT|0666);
if(msqid == -1){
printf("msg creat failed\n");
}
//获取消息类型为'888' 的消息
msgrcv(msqid,&getbuf,128,888,0);
printf("%s\n",getbuf.mtext);
//发送消息类型为'666'的消息
msgsnd(msqid,&send,strlen(send.mtext),0);
//删除队列
msgctl(msqid,IPC_RMID,NULL);
return 0;
}