消息队列概述
消息队列是消息的链表, 存放在内存中, 由内核维护
消息队列的特点 :
消息:有类型
消息:有格式
可实现消息的随机查询
允许一个或多个进程向它写入或者读取消息
从消息队列中读出消息,消息队列中对应的数据都会被删除
每个消息队列都有消息队列标识符, 消息队列的标识符是唯一
只有内核重启或人工删除消息队列时,该消息队列才会被删除
ftok 函数
#include <sys/msg.h>
/*
* 功能:
* 创建一个新的或打开一个已经存在的消息队列
* 不同的进程调用此函数,只要用相同的 key 值就能得到同一个消息队列的标识符
* 参数:
* key:IPC键值
* msgfig:标识函数的行为及 消息队列的权限
* IPC_CREAT:创建消息队列
* IPC_EXCL:检测消息队列的存在
* 位或权限位:消息队列位或权限位后可以设置消息队列的访问权限
* return:
* 成功:消息队列的标识符
* 失败:-1
*/
int msgget(key_t key, int msgfig);
//shell操作
//查看消息队列
ipcs -q
//删除信息队列
ipcrm -q xxx
//消息队列的消息的格式
// 消息类型必须是长整型的,结构体类型的第一个成员,类型下面是消息正文,正文可以有多个成员(任意数据类型)
typedef struct _msg
{
long mtype; //消息类型
char mtex[100]; //消息正文
// ... //消息正文有多个成员
}MSG;
发送消息
#include <sys/msg.h>
/*
* 功能:
* 将新消息添加到消息队列
* 参数:
* msqid:消息队列的标识符
* msgp: 待发送消息结构体的地址
* msgsz: 消息正文的字节数
* msgfig: 函数的控制属性
* 0:msgsnd 调用阻塞直到条件满足为止
* IPC_NOWAIT: 消息没有立即发送, 调用该函数的进程会立即返回
* return:
* 成功:0
* 失败:-1
*/
int msgsend(int msqid, const void *msgp, size_t msgsz, int msgfig)
接收消息
#include <sys/msg.h>
/*
*功能:
* 从标识符为 msqid 的消息队列中接收一个消息
* 接收消息成功,消息在消息队列中被删除
*参数:
* msqid: 消息队列的标识符
* msgp: 消息结构体的地址
* msgsz:消息正文的字节数
* msgtyp: 消息的类型
* = 0:返回 第一个消息
* > 0: 返回 消息类型为 msgtyp 的消息
* < 0: 返回队列中消息类型值小于或等于 msgtyp 绝对值的消息
* 如果这种消息有若干个,取类型值最小的消息
* msgflg: 函数的控制属性
* 0: msgrcv 调用阻塞直到接收消息成功为止
* MSG_NOERROR: 若返回的消息字节数比 nbytes 字节数多,则消息就会截短到 nbytes 字节,且不通知消息发送进程
* IPC_NOWAIT: 调用进程会立即返回。若没有收到消息, 立即返回-1
*return:
* 成功:读取消息的长度
* 失败:-1
*/
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
消息队列的控制
#include <sys/msg.h>
/*
*功能:
* 对消息队列进行各种控制, 如修改消息队列的属性, 或删除消息消息队列
*参数:
* msgid:消息队列的标识符
* cmd: 函数功能的控制
* IPC_RMID: 删除由 msqid 指示的消息队列, 将它从系统中删除并破坏相关数据结构
* IPC_STAT: 将 msqid 相关的数据结构中各个元素的当前值存入到由 buf 指向的结构中
* IPC_SET: 将 msqid 相关的数据结构中的元素设置为由 buf 指向的结构中的对应值
* buf: msqid_ds 数据类型的地址,用来存放或更改消息队列的属性
*return:
* 成功:0
* 失败:-1
*/
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
写
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct _msg
{
long mtype;
char mtext[50];
}MSG;
int main(int argc, char *argv[])
{
key_t key;
int msgqid;
MSG msg;
key = ftok(".", 2012);
msgpid = msgget(key, IPC_CREAT | 0666);
if(msgpid == -1)
{
perror("msgget");
exit(-1);
}
msg.mtype = 10;
strcpy(msg.mtext, "hello world");
msgsnd(msgpid, &msg, sizeof(msg.mtext), 0);
return 0;
}
读
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
typedef struct _msg
{
long mtype;
char mtext[50];
}MSG;
int main(int argc, char *argv[])
{
key_t key;
int msgqid;
MSG msg;
key = ftok(".", 2012);
msgpid = msgget(key, IPC_CREAT | 066);
if(msgpid == -1)
{
perror("msgget");
exit(-1);
}
msgrcv(msgqid, &msg, sizeof(msg.mtext), 10 , 0);
printf("msg.mtext = %s\n", msg.mtext);
msgctl(msgqid, IPC_RMID, NULL);
return 0;
}