1. 相关概念
消息队列是IPC对象的一种
消息队列由消息队列ID来唯一标识
消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。
消息队列可以按照类型来发送/接收消息
2. 相关函数
1 -- msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:
创建或者打开一个消息队列,得到消息队列id
参数:
key:
键值,唯一的键值确定唯一的消息队列
如何设置键值:
自己直接定义一个键值
使用ftok函数获取键值
msgflg:
标志位
一般设置为 IPC_CREAT | 0777
返回值:
成功:
消息队列id
失败:
-1
2 -- ftok
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:获取键值
参数:
pathname:
路径名
proj_id:
自定义的值,只取前八位
返回值:
成功:
键值
失败:
-1
3 -- msgctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
控制一个消息队列
参数:
msqid:
消息队列id
cmd:
具体控制
IPC_STAT 获取消息队列属性信息
IPC_SET 设置消息队列属性信息
IPC_RMID 删除一个消息队列
msqid_ds:消息队列属性结构体
返回值:
成功:
0
失败:
-1
4 -- msgsnd
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:
向一个消息队列中写入数据
参数:
msqid:
消息队列id
msgp:
要写入的数据,需要自己定义一个结构体
struct msg_buf{
long type; //消息类型,必须有且类型也不能变
用于读取数据时,可以指定消息的类型来读取
char mtext[32]; //消息正文具体要写入的数据,大小自己定义,类型也可以自定义
};
msgsz:
消息正文的大小,就是mtext的大小,一定不是第二个参数的大小
msgflg:
标志位
0 阻塞
IPC_NOWAIT 非阻塞
返回值:
成功:
0
失败:
-1
5 -- msgrcv
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,
long msgtyp, int msgflg);
功能:
从消息队列中读取数据
参数:
msqid:
消息队列id
msgp:
保存读取的数据
msgsz:
消息正文大小
msgtyp:
消息类型
0 按照顺序读取一个消息
>0 按照顺序读取第一个消息类型为当前参数的消息
<0 按照顺序读取第一个消息类型小于等于这个参数的绝对值的类型的消息
msgflg:
标志位
0 阻塞
IPC_NOWAIT 非阻塞
返回值:
成功:
接收到的数据的大小
失败:
-1
3. 创建和删除消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
//使用ftok函数获取键值
key_t key;
if((key = ftok(".", 1000)) == -1)
{
perror("ftok error");
exit(1);
}
//ftok函数获取的健值就是这个函数的第二个参数的后8位、第一个参数
//对应文件的设备好的后8位以及这个文件inode号的后16位,共同组成键值
// printf("key = %#x\n", key);
// struct stat mystat;
// stat(".", &mystat);
// printf("dev_num = %x\n", mystat.st_dev);
// printf("inode = %x\n", mystat.st_ino);
// printf("1000 = %#x\n", 1000);
//创建一个消息队列
int msgid;
if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
{
perror("msgget error");
exit(1);
}
puts("--------------------------------------------");
system("ipcs -q");
puts("--------------------------------------------");
//删除消息队列
if(msgctl(msgid, IPC_RMID, NULL) == -1)
{
perror("msgctl error");
exit(1);
}
puts("--------------------------------------------");
system("ipcs -q");
puts("--------------------------------------------");
return 0;
}
4. 将数据写入消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
typedef struct{
long type;
int id;
char name[32];
int score;
}MSG;
#define DATASIZE (sizeof(MSG) - sizeof(long))
int main(int argc, char const *argv[])
{
//使用ftok函数获取键值
key_t key;
if((key = ftok(".", 1000)) == -1)
{
perror("ftok error");
exit(1);
}
//创建一个消息队列
int msgid;
if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
{
perror("msgget error");
exit(1);
}
puts("--------------------------------------------");
system("ipcs -q");
puts("--------------------------------------------");
MSG msg1 = {1, 1001, "zhangsan", 90};
MSG msg2 = {2, 1002, "lisi", 100};
MSG msg3 = {3, 1003, "wangwu", 92};
MSG msg4 = {4, 1004, "zhaoliu", 88};
msgsnd(msgid, &msg1, DATASIZE, 0);
msgsnd(msgid, &msg2, DATASIZE, 0);
msgsnd(msgid, &msg3, DATASIZE, 0);
msgsnd(msgid, &msg4, DATASIZE, 0);
puts("--------------------------------------------");
system("ipcs -q");
puts("--------------------------------------------");
return 0;
}
5. 从消息队列中读取数据
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
typedef struct{
long type;
int id;
char name[32];
int score;
}MSG;
#define DATASIZE (sizeof(MSG) - sizeof(long))
int main(int argc, char const *argv[])
{
//使用ftok函数获取键值
key_t key;
if((key = ftok(".", 1000)) == -1)
{
perror("ftok error");
exit(1);
}
//创建一个消息队列
int msgid;
if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
{
perror("msgget error");
exit(1);
}
puts("--------------------------------------------");
system("ipcs -q");
puts("--------------------------------------------");
MSG msg;
ssize_t bytes;
if((bytes = msgrcv(msgid, &msg, DATASIZE, -3, 0)) == -1)
{
perror("msgrcv error");
exit(1);
}
printf("bytes = %ld, id:%d,name:%s,score:%d\n", bytes, msg.id, msg.name, msg.score);
puts("--------------------------------------------");
system("ipcs -q");
puts("--------------------------------------------");
return 0;
}