Linux系统编程—消息队列
1、消息队列相关函数
// 创建和获取 ipc 内核对象
int msgget(key_t key, int flags);
// 将消息发送到消息队列
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// 从消息队列获取消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
// 查看、设置、删除 ipc 内核对象(用法和 shmctl 一样)
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
2、消息数据格式
struct Msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[50]; /* message data */
};
3、msgsnd函数
msgsnd 函数用于将数据发送到消息队列。如果该函数被信号打断,会设置 errno 为 EINTR。
使用时需要导入以下头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgid: 由msgget函数返回的消息队列标识码。
msg_ptr:是一个指针,指针指向准备发送的消息。
msg_sz:是msg_ptr指向的消息长度,这个长度不能保存消息类型的那个“long int”长整型计算在内。
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情。
操作成功,返回“0”,如果失败,则返回“-1”。
4、msgrcv 函数
msgrcv 函数从消息队列取出消息后,并将其从消息队列里删除。
使用时,如果没有包含上面那3个头文件,需包含再使用。
函数原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgid: 由msgget函数返回的消息队列标识码。
msg_ptr:是一个指针,指针指向准备接收的消息。
msgsz:是msg_ptr指向的消息长度,这个长度不能保存消息类型的那个“long int”长整型计算在内。
msgtype:它可以实现接收优先级的简单形式。
msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事。
操作成功,返回实际放到接收缓冲区里去的字符个数,如果失败,则返回“-1”。
5、示例
这个程序是向消息队列发消息;
#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
#include<stdio.h>
using namespace std;
struct Msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[50]; /* message data */
};
int main()
{
int msg_id, msgSendRes;//msgSendRes接收msgsnd的返回值 -1失败
struct Msgbuf msgData;//发送消息携带的数据结构体
bzero(msgData.mtext, sizeof(msgData.mtext));//msgData.mtext内存清0
msg_id = msgget(key_t(123), IPC_CREAT | 0666);//创建消息队列 失败:-1 成功:返回消息的标识符
if (msg_id == -1)
{
perror("msgget error");
return -1;
}
//数据准备
strcpy(msgData.mtext,"hello world");
msgData.mtype = 1;//发送端mtype设置成多少,接收端对应的mtype也是多少
msgSendRes = msgsnd(msg_id, &msgData, sizeof(msgData.mtext), 0);//添加消息到消息队列
//cout << msgData.mtext << endl;
if (msgSendRes == -1)
{
perror("msgsnd error");
return -1;
}
return 0;
}
在Linux环境下,输入命令ipcs
,查看消息队列:
此时说明,我们的消息已经写入消息队列中,等待读取。
接收消息代码:
#include<iostream>
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
using namespace std;
struct Msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[50]; /* message data */
};
int main()
{
int msg_id;//接收msgget的返回值
ssize_t msgrcvRes;//接收msgrcv函数的返回值 -1 失败
struct Msgbuf msgData;//数据结构体
bzero(msgData.mtext, sizeof(msgData.mtext));//msgData.mtext清0
msg_id = msgget(key_t(123), IPC_CREAT | 0666);//创建消息队列 成功:返回消息标识符 失败:-1
if (msg_id == -1)
{
perror("msgget error");
return -1;
}
msgrcvRes = msgrcv(msg_id, &msgData, sizeof(msgData.mtext), 1, 0);//从消息队列里检索消息
if(msgrcvRes==-1)
{
perror("msgrcv error");
return -1;
}
cout << "检索到的消息为:" << msgData.mtext << endl;
return 0;
}
运行此程序:
可以看到已经检索到消息队列里面的消息;再次输入命令ipcs
,可以发现消息队列里面的消息数已经减一。