消息队列的本质是消息的链表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
接收进程可以独立地接收含有不同类型的数据结构。
目录
几个宏:
MSGMAX 可发送是最长消息的长度 2048
MSGMNB 特定队列的最大字节长度(亦即队列中所有消息之和) 4096
MSGMNI 系统中最大消息列数 50
MSGTOL 系统中最大消息数 50
特点:
- 1,消息具有特定的格式和特定的优先级。
- 2,独立于发送和接收进程。进程终止时,消息队列及其内容并不会删除。
- 3,可以实现消息的随机查询,不一定是按先进先出读取,也可以按消息的类型读取。
API:
- 1)msgget()创建和访问消息队列。
int msgget(key_t key, int flag);
- 如果没有与键值key相对应的消息队列,并且flag中包含了
IPC_CREAT
标志位。 - key参数为
IPC_PRIVATE
。
- 2)msgsend()把消息添加到消息队列。
int msgsnd(int msqid, const void *ptr, size_t size, int flag);
- ptr是一个指向准备发送消息的指针,但是消息的数据结构有一定的要求,指针ptr所指向的消息结构一定要是一个长整型变量开始的结构体,接收成员将用这个成员来确定消息的类型。 long int message_type;
- size是ptr指向的消息的长度,该长度不包括长整型消息类型变量的长度。
- 3)msgrcv()从一个消息队列获取消息。
int msgrcv(int msqid, void *ptr, size_t size, long type, int flag);
- 4)msgctl()控制消息队列。
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
- 其中 第三个参数 msqid_ds的结构体
struct msqid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
例子:
msg_server.c
#include <uinstd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
// 用于创建一个唯一的key
#define MSG_FILE "/etc/passwd"
// 消息结构
struct msg_form {
long mtype;
char mtext[256];
};
int main()
{
int msqid;
key_t key;
struct msg_form msg;
// 获取key值
if((key = ftok(MSG_FILE,'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 打印key值
printf("Message Queue - Server key is: %d.\n", key);
// 创建消息队列
if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
{
perror("msgget error");
exit(1);
}
// 打印消息队列ID及进程ID
printf("My msqid is: %d.\n", msqid);
printf("My pid is: %d.\n", getpid());
// 循环读取消息
for(;;)
{
msgrcv(msqid, &msg, 256, 888, 0);// 返回类型为888的第一个消息
printf("Server: receive msg.mtext is: %s.\n", msg.mtext);
printf("Server: receive msg.mtype is: %d.\n", msg.mtype);
msg.mtype = 999; // 客户端接收的消息类型
sprintf(msg.mtext, "hello, I'm server %d", getpid());
msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
}
return 0;
}
msg_client.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
// 用于创建一个唯一的key
#define MSG_FILE "/etc/passwd"
// 消息结构
struct msg_form {
long mtype;
char mtext[256];
};
int main()
{
int msqid;
key_t key;
struct msg_form msg;
// 获取key值
if ((key = ftok(MSG_FILE, 'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 打印key值
printf("Message Queue - Client key is: %d.\n", key);
// 打开消息队列
if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
{
perror("msgget error");
exit(1);
}
// 打印消息队列ID及进程ID
printf("My msqid is: %d.\n", msqid);
printf("My pid is: %d.\n", getpid());
// 添加消息,类型为888
msg.mtype = 888;
sprintf(msg.mtext, "hello, I'm client %d", getpid());
msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
// 读取类型为777的消息
msgrcv(msqid, &msg, 256, 999, 0);
printf("Client: receive msg.mtext is: %s.\n", msg.mtext);
printf("Client: receive msg.mtype is: %d.\n", msg.mtype);
return 0;
}
执行: