Linux 学习笔记18 消息队列
消息队列概念
消息队列与 FIFO 很相似,都是一个队列结构,都可以有多个进程往队列里面写信息,多个进程从队列中读取信息。但 FIFO 需要读、写的两端事先都打开,才能够开始信息传递工作。而消息队列可以事先往队列中写信息,需要时再打开读取信息。
- 消息队列与管道的不同之处
消息队列常用函数
创建消息队列
-
int msgget(key_t key, int msgflg);
参数解析:
- key 是唯一标识一个消息队列的关键字,如果为 IPC_PRIVATE(值为 0),用创建一个只有创建者进程才可以访问的消息队列,可以用于父子间通信;
- msgflg 指明队列的访问权限和创建标志,创建标志的可选值为 IPC_CREAT和 IPC_EXCL
msgget 代码如下:
#include <func.h>
//获取消息队列
int main(int argc,char * argv[])
{
int msgid;
int ret;
msgid=msgget(1000,IPC_CREAT|0600);//消息队列大小由系统默认设置
ERROR_CHECK(ret,-1,"msgget");
return 0;
}
执行效果如下:
msqid:消息队列id
used-bytes : 已往消息队列写入的数据
发送消息队列 msgsnd
-
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数解析:
- msqid:消息队列id, msgget的返回值
- msgp:变长结构体,需自己定义,详细如下
-
struct msgbuf { long mtype; /* message type, must be > 0 */ //消息类型 char mtext[1]; /* message data */ //消息大小,自定义 };
- msgsz:消息队列大小
- msgflg:一般填0
接收消息队列 msgrcv
-
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
参数解析
- msqid:消息队列id, msgget的返回值
- msgp:变长结构体同上
- msgsz:同上
- msgtype :消息类型,在结构体 msgbuf 中已定义
- msgflg :同上。
msgsnd && msgrcv 代码如下:
#include <func.h>
typedef struct msgbuf_b{
//变长结构体
long mtype;
char mtext[128];
}MSG;
int main(int argc,char * argv[])
{
int msgid;
int ret;
MSG msg;
msgid=msgget(1000,IPC_CREAT|0600);//消息队列大小由系统默认设置
if(!fork())
{//子进程读
msg.mtype=1;//消息类型设置为1
strcpy(msg.mtext,"I am Jarvis\n");
ret=msgsnd(msgid,&msg,strlen(msg.mtext),0);
ERROR_CHECK(ret,-1,"msgsnd");
printf("Child mark send %d bytes\n",ret);//正确返回0,错误返回-1
}else
{//父进程写
bzero(&msg,sizeof(msg));
ret=msgrcv(msgid,&msg,sizeof(msg.mtext),1,0);//第4个参数填0时按顺序读队列,填1时读type为1的节点
printf("ret=%d,type=%ld,%s\n",ret,msg.mtype,msg.mtext);
wait(NULL);
}
return 0;
}
执行效果如下:
- 只往消息队列中发送,没有接受的情况:
#include <func.h>
//验证只发送不接收,消息会存放在消息队列中
//
typedef struct msgbuf_b{
//变长结构体
long mtype;
char mtext[128];
}MSG;
int main(int argc,char * argv[])
{
int msgid;
int ret;
MSG msg;
msgid=msgget(1000,IPC_CREAT|0600);//消息队列大小由系统默认设置
msg.mtype=1;
strcpy(msg.mtext,"I am Jarvis\n");
ret=msgsnd(msgid,&msg,strlen(msg.mtext),0);
ERROR_CHECK(ret,-1,"msgsnd");
return 0;
}
执行效果如下:
由图可知,往消息队列中写入 12 个字节,因此 used-bytes 变为12。
补充:删除消息队列命令
-
ipcrm -q 消息队列ID