由内核负责管理的一个管道,可以按顺序发送消息包(消息类型+消息内容),可以全双工工作。可以不按消息的顺序接收消息
用到的函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
Int msgget(key_t key, int msgflg);
功能:创建/获取消息队列
key:IPC键值,由ftok函数自动生成
msgflg:
0 获取消息队列
IPC_CREAT 创建消息队列
IPC_EXCL 如果存在则创建失败
返回值:消息队列标识
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送消息
msqid:消息队列标识,msgget的返回值
msgp:结构指针
struct msgbuf
{
long mtype; 消息类型 /* message type, must be > 0 */
char mtext[1]; 消息内容 /* message data */
};
msgsz:消息的长度,不包括消息类型,sizeof(msgbuf)-4 ( 要-4 否则会内存奔溃)
msgflg:
0 阻塞,当消息队列满时,等待
1 不阻塞,当消息队列满时,不等待
IPC_NOWAIT 不阻塞,当消息队列满时,不等待
返回值:成功发送返回0,失败返回-1
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:从消息队列中按类型获取消息
msqid:消息队列标识,msgget的返回值
msgp:
struct msgbuf
{
long mtype; 消息类型 /* message type, must be > 0 */
char mtext[1]; 消息内容 /* message data */
};
msgsz:消息的长度,不包括消息类型,可以长一些。
msgtyp:要接收的消息类型
msgflg:
0 阻塞,消息队列中是否有对应类型的消息,没有则等待
1 不阻塞,消息队列中没有对应类型的消息则返回
MSG_NOERROR 消息类型正确,而消息的实际长度大于msgsz,则不接收消息并返回-1。
如果msgflg带MSG_NOERROR标志,则把多余的消息截取,成功接收。
IPC_NOWAIT 如果消息队列没有要接收的消息,则不等待,返回-1。
MSG_EXCEPT 接收消息队列中第一个消息类型不是msgtyp的消息,编译时添加-D_GNU_SOURCE参数。
返回值:成功接收到的字节数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:删除消息队列,设置或获取消息队列的属性
msqid:消息队列标识,msgget的返回值
cmd:
IPC_STAT 获取消息队列的属性
IPC_SET 设置消息队列的属性
IPC_RMID 删除消息队列 buf = NULL
返回值:成功返回0,失败返回-1
struct msqid_ds
{
struct ipc_perm msg_perm; // 权限
time_t msg_stime; // 最后一个消息发送时间
time_t msg_rtime; // 最后一次消息接收时间
time_t msg_ctime; // 最后一次修改时间
unsigned long __msg_cbytes; // 消息队列中的字节数
msgqnum_t msg_qnum; // 消息队列中消息的个数
msglen_t msg_qbytes; // 消息队列中容纳的最大字节数
pid_t msg_lspid; // 最后一次发送消息进程
pid_t msg_lrpid; // 最后一次接收消息进程
}
***编程模型***
进程A 进程B
生成IPC键值 ftok 生成IPC键值 ftok
创建消息队列 msgget 获取消息队列 msgget
发送消息 msgsnd 接收消息 msgrev
删除消息队列 msgctl ...
#include "struct.h" 头文件定义结构体:
#ifndef STRUCT_H
#define STRUCT_H
typedef struct Msg
{
long type;
char data[256];
}Msg;
#endif//STRUCT_H
进程A实现接收 :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "struct.h"
int main()
{
//1.创建IPC键值
key_t key = ftok(".",888);
//2.创建消息队列
int msgid = msgget(key,IPC_CREAT|0644);
if(0 > msgid)
{
perror("msgget");
return -1;
}
Msg msg = {666};//定义类型
//3. 开始通信
while(1)
{
printf(">");
gets(msg.data);
msgsnd(msgid,&msg,sizeof(Msg)-sizeof(msg.type),0);
if(0 == strcmp(msg.data,"quit"))
{
printf("通信结束\n");
break;
}
}
//3.删除消息队列
if(0 > msgctl(msgid,IPC_RMID,NULL))
{
perror("msgctl");
return -1;
}
return 0;
}
进程B实现发送消息:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "struct.h"
int main()
{
//1.创建IPC键值
key_t key = ftok(".",888);
//2. 获取消息队列
int msgid = msgget(key,0);
if(0 > msgid)
{
perror("msgget");
return -1;
}
Msg msg = {};
//3. 接收消息
while(1)
{
msgrcv(msgid,&msg,sizeof(Msg),666,0);
printf("read: %s\n",msg.data);
if(0 == strcmp(msg.data,"quit"))
{
printf("通讯结束\n");
break;
}
}
return 0;
}