一 what
消息队列也是进程间通信的一种通信方式,在内核中创建一个消息队列对象,不同的进程中,通过msgid来访问这个消息队列实现进程间通信
|---| |---|
| A | | B |
|---| |---|
------------------------------------
|-------------|
| | 消息队列
|-------------|
-------------------------------------
之前在介绍管道的时候,管道也是一个队列,它是一个顺序队列,那么这个队列和消息队列有什么区别呢?
消息队列是一个链式队列
相关函数
1. 创建或者打开消息队列的函数 msgget
所需头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型: int msgget(key_t key, int flag)
参数: key 和消息队列关联的key值
flag 消息队列的访问权限
返回值: 成功,消息队列ID,出错 -1
2. 关闭: msgctl
原型: int msgctl(int msgqid, int cmd, struct msqid_ds *buf)
参数: msgqid 消息队列ID
cmd IPC_STAT 读取消息队列的属性,并将其保存在buf指向的缓冲区中
IPC_SET 设置消息队列的属性,这个值取自buf参数
IPC_RMID 从系统中删除消息队列
buf 消息缓冲区
返回值: 成功 0,出错 -1
3. 发送: msgsnd
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型: int msgsnd(int msgqid, const void *msgp, size_t size, int flag)
参数: msgqid 消息队列ID
msgp 指向消息的指针,常用消息结构msgbuf如下
struct msgbuf {
long mtype; //消息类型
char mtext[N]; //消息正文
};
size 消息正文的字节数
flag IPC_NOWAIT 消息没有发送完成也会立即返回
0: 直到发送完成函数才会返回
返回值: 成功 0,出错 -1
4. 读取: msgrcv
原型: int msgrcv(int msgqid, void *msgp, size_t size, long msgtype, int flag)
参数: msgqid 消息队列ID
msgp 接收消息的缓冲区
size 要接收消息的字节数
msgtype 0 接收消息队列中第一个消息
大于0 接收消息队列中第一个类型为msgtype的消息
小于0 接收消息队列中类型值不大于msgtype的绝对值且类型值又最小的消息
flag IPC_NOWAIT 没有消息,会立即返回
0: 若无消息则会一直阻塞
返回值: 成功 接收消息的长度,出错 -1
二 how
- 创建消息队列
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"
int main(int argc, char *argv[])
{
int msgid;
msgid = msgget(IPC_PRIVATE, 0777);
if (msgid < 0) {
printf("create msg queue fail\n");
return -1;
}
printf("create msg queue sucess, msgid = %d\n", msgid);
system("ipcs -q");
return 0;
}
- 利用消息队列实现进程间通信
发送函数
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"
struct msgbuf {
long type; //消息类型
char voltage[124]; //消息正文
char ID[4];
};
int main(int argc, char *argv[])
{
int msgid, readret, key;
struct msgbuf sendbuf;
key = ftok("./a.c", 'a');
if (key < 0){
printf("create key fail\n");
return -1;
}
msgid = msgget(key, IPC_CREAT|0777);
if (msgid < 0) {
printf("create msg queue fail\n");
return -1;
}
printf("create msg queue sucess, msgid = %d\n", msgid);
system("ipcs -q");
// write message queue
sendbuf.type = 100;
while(1) {
memset(sendbuf.voltage, 0, 124); //clear send buffer
printf("please input message:\n");
fgets(sendbuf.voltage, 124, stdin);
//start write msg to msg queue
msgsnd(msgid, (void *)&sendbuf, strlen(sendbuf.voltage), 0);
}
return 0;
}
接收函数
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"
struct msgbuf {
long type; //消息类型
char voltage[124]; //消息正文
char ID[4];
};
int main(int argc, char *argv[])
{
int msgid, key;
struct msgbuf readbuf;
key = ftok("./a.c", 'a');
if (key < 0){
printf("create key fail\n");
return -1;
}
msgid = msgget(key, IPC_CREAT|0777);
if (msgid < 0) {
printf("create msg queue fail\n");
return -1;
}
printf("create msg queue sucess, msgid = %d\n", msgid);
system("ipcs -q");
// read message queue
while(1) {
memset(readbuf.voltage, 0, 124); //clear recv buffer
//start read msg to msg queue
msgrcv(msgid, (void *)&readbuf, 124, 100, 0);
printf("recv data from message queue:%s", readbuf.voltage);
}
return 0;
}