一、什么是消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
二、特点
-
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
-
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
-
消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
三、常用API
1.创建/打开消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
参数:
key_t key: 创建新的消息队列
int msgflg: 赋予新消息队列的权限,如:IPC_CREAT|0777
2.添加消息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
int msqid: 消息队列标识符
const void *msgp: msgp是一个任何类型的结构体,是消息队列的地址
size_t msgsz: 要发送消息的大小,不含消息类型占用的4个字节,即mtext的长度
int msgflg: 默认写0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列
const void *msgp的结构体如下:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
3.读取消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数:
int msqid: 消息队列标识符
void *msgp: 存放消息的结构体,结构体类型要与msgsnd函数发送的类型相同
size_t msgsz: 要接收消息的大小,不含消息类型占用的4个字节
long msgtyp: 要读消息的类型,如写:888
int msgflg: 默认写0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待
4.控制消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
int msqid: 消息队列标识符
int cmd: 一般写IPC_RMID
struct msqid_ds *buf:一般写NULL
返回值:成功返回0,失败返回-1
5.ftok
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
key_t ftok( char * fname, int id );
参数:
fname就时你指定的文件名(该文件必须是存在而且可以访问的)
id是子序号,虽然为int,但是只有8个比特被使用(0-255)。
返回值:
当成功执行的时候,一个key_t值将会被返回,否则 -1 被返回。
四、编程示例
msgGet.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct msgbuf{
long mtype;
char mtext[128];
};
int main()
{
struct msgbuf readBuf;
struct msgbuf sendBuf = {988,"Thank you,welcome"};
key_t key;
key = ftok(".",'z');//获取key值
printf("key=%x\n",key);
int msgid = msgget(key,IPC_CREAT|0777);//获取消息队列
if(msgid == -1){
printf("get queue failed\n");
}
msgrcv(msgid,&readBuf,sizeof(readBuf.mtext),888,0);//从消息队列读取内容
printf("read from queue:%s\n",readBuf.mtext);
msgsnd(msgid,&sendBuf,strlen(sendBuf.mtext),0);//往消息队列写入内容
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
msgSend.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct msgbuf{
long mtype;
char mtext[128];
};
int main()
{
struct msgbuf sendBuf = {888,"this is message from queue"};
struct msgbuf readBuf;
key_t key;
key = ftok(".",'z');//获取key值
printf("key=%x\n",key);
int msgid = msgget(key,IPC_CREAT|0777);//获取消息队列
if(msgid == -1){
printf("get queue failed\n");
}
msgsnd(msgid,&sendBuf,strlen(sendBuf.mtext),0);//往消息队列发送内容
printf("send over\n");
msgrcv(msgid,&readBuf,sizeof(readBuf.mtext),988,0);//从消息队列读取内容
printf("return from get:%s\n",readBuf.mtext);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}