消息队列:
基本特点:是由内核负责维护管理的数据链表,通过消息类型收发数据。
int msgget(key_t key, int msgflg);
功能:创建/获取消息队列
key:IPC键值
msgflg:
IPC_CREAT 创建消息队列
IPC_EXCL 如果消息队列已经存在则返回错误
mode_flags:创建消息队列时需要提供权限
返回值:成功返回IPC标识符,错误返回-1。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送数据
msqid:IPC标识符
msgp:要发送的消息的首地址
struct msgbuf {
long mtype; // 消息类型
char mtext[5]; // 数据
};
msgsz:数据的字节数,不包含消息类型。
msgflg:
阻塞一般写0。
IPC_NOWAIT 当消息队列满时,不等待立即返回。
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:从消息队列中读取数据
msqid:IPC标识符
msgp:存储数据结构首地址
msgsz:结构体的字节数
msgtyp:消息类型
>0 读取消息类型等于msgtyp的消息。
=0 读取消息队列第一条消息。
<0 读取消息类型小于abs(msgtyp)的消息,如果有多个则读取最小的。
msgflg:
IPC_NOWAIT 消息类型不符合时不阻塞,立即返回。
MSG_EXCEPT 如果msgtyp>0,则读取第一个消息类型不是msgtyp的消息。
MSG_NOERROR 如果不包含些标志,消息实际长度>msgsz,则返回错误不读取数据,若包含此标志,则读取msgsz个字节。
返回值:成功读取到的字节数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:删除/获取消息的属性
msqid:IPC标识符
cmd:
IPC_STAT 获取消息队列的属性
IPC_SET 设置消息队列的属性
IPC_RMID 删除消息队列
buf:
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
pid_t msg_lrpid; 最后接收者PID
};
编程模型:
进程A 进程B
创建消息队列 获取消息队列
发送消息 接收消息
接收消息 发送消息
删除消息队列
在这里插入代码片
```#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "message.h"
int main(int argc,const char* argv[])
{
// 创建消息队列
int msgid = msgget(ftok(".",120),IPC_CREAT|0644);
if(0 > msgid)
{
perror("msgget");
return -1;
}
Msg msg = {};
for(;;)
{
msg.type = 5;
printf(">>>");
gets(msg.data);
// 发送消息
if(msgsnd(msgid,&msg,strlen(msg.data)+1,0))
{
perror("msgsne");
break;
}
if(0 == strcmp(msg.data,"quit")) break;
// 接收消息
if(0 == msgrcv(msgid,&msg,MSGMAX,6,0))
{
perror("msgrcv");
break;
}
printf("recv:%s\n",msg.data);
if(0 == strcmp(msg.data,"quit")) break;
}
printf("通信结束!\n");
usleep(1000);
// 删除消息队列
if(msgctl(msgid,IPC_RMID,NULL))
{
perror("msgctl");
return -1;
}
return 0;
```c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "message.h"
int main(int argc,const char* argv[])
{
// 创建消息队列
int msgid = msgget(ftok(".",120),IPC_CREAT|0644);
if(0 > msgid)
{
perror("msgget");
return -1;
}
Msg msg = {};
for(;;)
{
// 接收消息
if(0 == msgrcv(msgid,&msg,MSGMAX,5,0))
{
perror("msgrcv");
break;
}
printf("recv:%s\n",msg.data);
if(0 == strcmp(msg.data,"quit")) break;
msg.type = 6;
printf(">>>");
gets(msg.data);
// 发送消息
if(msgsnd(msgid,&msg,strlen(msg.data)+1,0))
{
perror("msgsne");
break;
}
if(0 == strcmp(msg.data,"quit")) break;
}
printf("通信结束!\n");
return 0;
}