消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。创建一个新的消息队列或者打开一个已经存在的队列所使用的系统调用为msgget
- key:表示用户态所给出的key值(相当于文件名),
- flag:参数表示对该队列所拥有的权限。调用成功后会返回一个msgid(相当于文件描述符)。
Msgctl函数可以对消息队列执行多种操作,他和另外两个与信号量和共享内存有关的函数semctl,shmctl是类似的函数。
- msgid:参数表示要作用的消息队列的id
- cmd:参数表示要对该消息队列所执行的操作,
- buf:表示一个msgid_ds类型的结构体指针,若不用返回什么数时,最后一个参数也可为0.
调用msgsnd系统调用函数将数据放到消息队列的尾端。
- msgid:消息队列id
- ptr:指向mymsg结构(要传输的消息的结构,里面包含所要传输数据的类型)的指针,接收者可以使用消息类型以非先进先出的次序取出消息
- nbytes:要传输数据的大小
- falg:该参数可以被指定为IPC_NOWAIT,类似于非阻塞标志,若消息队列已满,则指定IPC_NOWAIT使得msgsnd函数立即出错返回EAGAIN,也可以指定为0(不阻塞)。
msgrcv系统调用用来从队列中取用消息:
- msgid:消息队列id
- ptr:存放实际消息数据的缓冲区
- nbytes:缓冲区的长度
- type:指定想要获取的消息类型
- flag:一般情况下指定为0
我们来看一个例子:
用a进程向消息队列中发送数据,b进程接收并输出
//a.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/msg.h>
typedef struct data
{
long type;
char text[512];
}Data;
int main()
{
int msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
assert(msgid != -1);
Data val;
memset(&val, 0, sizeof(Data));
val.type = 1000;
strcpy(val.text, "hello");
msgsnd(msgid, &val, strlen(val.text), 0);
memset(&val, 0, sizeof(Data));
val.type = 2000;
strcpy(val.text, "world");
msgsnd(msgid, &val, strlen(val.text), 0);
exit(0);
}
b.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/msg.h>
typedef struct data
{
long type;
char text[512];
}Data;
int main()
{
int msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
assert(msgid != -1);
Data val;
memset(&val, 0, sizeof(Data));
//char buff[128] = {0};
msgrcv(msgid, &val, sizeof(Data), 1000, 0);
printf("type = %d, text = %s\n", val.type, val.text);
msgrcv(msgid, &val, sizeof(Data), 2000, 0);
printf("type = %d, text = %s\n", val.type, val.text);
exit(0);
}
运行结果如下: