Linux进程通信——消息队列

目录

概念

特点

创建

头文件

常用API

msgget()

msgsnd()

msgrcv()

代码展示


概念

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

特点

1.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。(消息队列是结构体)
2.消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除
3.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次席读取,也可以按消息的类型读取

两者的队列ID需相同才能成功实现存放数据和取数据,如图都指向队列1的最后一个。

消息队列与管道的不同点:写入读取后内容还存在于Linux内核中,不会跟管道一样读取完就消失。

创建

从消息队列特点可知,两个进程分别需要同队列ID相同的队列进行写入数据并读取数据,此时要想成功创建一个消息队列,需关心两个问题:

问题一:进程B如何添加消息到队列

问题二:进程A如何读取队列的消息

头文件

#include <sys/msg.h>

常用API

msgget()

创建或打开消息队列:成功返回队列ID,失败返回-1

int msgget(key_t key, int flag);
key是一个索引值,为非负数,将通过索引值在Linux内核找到队列
flag打开队列的方式

在以下两种情况下,msgget将创建一个新的消息队列:
1、如果没有与键值key相对应的消息队列,并且flag中包含了IPC_CREAT标志位。

msgget(key,IPC_CREAT);

2、key参数为IPC_PRIVATE

msgget(key,IPC_PRIVATE);

msgsnd()

添加消息:成功返回0,失败返回-1

int msgsnd(int msqid, const void *ptr, size_t size, int flag);

msqid:消息队列的ID
ptr:写入的数据,指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下:

struct msgbuf
{
    long mtype; //消息类型,必须大于0
    char mtext[1];//消息文本 
};

size:数据的长度
flag:0,表示忽略,表示进程将被阻塞直到函数可以从队列中得到符合条件的消息为止;(还有许多,此处省略)

msgrcv()

读取消息:成功返回消息数据的长度,失败返回-1

int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);

msqid:消息队列的ID
ptr:写入的数据,指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下:

struct msgbuf
{
    long mtype; //消息类型,必须大于0
    char mtext[1];//消息文本 
};

type:消息类型

type = 0返回队列中的第一个消息
type >0返回队列中消息类型为 type 的第一个消息
type< 0返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息

可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。

size:数据的长度

flag:0,表示忽略,表示进程将被阻塞直到函数可以从队列中得到符合条件的消息为止;(还有许多,此处省略)

代码展示

get.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msgbuf
{
	long mtype;
    char mtext[128];
};


int main()
{
	int msgId;//创建消息队列ID
	struct msgbuf readBuf;//定义一个读取数据的结构体

	msgId = msgget(1234,IPC_CREAT|0777);//在内核中打开或建立键值为1234的,权限为0777的消息队列
	if(msgId == -1)//如果创建失败则执行下面代码
	{
		printf("create queue failed\n");
	}

	msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);//从队列中获取888类型的数据并存放到结构体的mtext中,如果队列中未出现888类型的数据,则程序阻塞在这里,这里的888需要与写入队列类型数据一致
	printf("read from queue:%s\n",readBuf.mtext);

	struct msgbuf sendBuf = {999,"thank you for reach\n"};//读取完毕后将字符串内容写入到999类型的数据中,这里的999类型需要与读取的类型数据一致
	msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);//将上一行的结构体数据写入1234消息队列中
	
	return 0;
}

send.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf
{
	long mtype;
    char mtext[128];
};


int main()
{
	int msgId;
	struct msgbuf sendBuf = {888,"this is message from queue\n"};//将字符串内容写入到888类型的数据中,这里的888类型需要与读取的类型数据一致
    struct msgbuf readBuf;

	msgId = msgget(1234,IPC_CREAT|0777);
	if(msgId == -1)
	{
		printf("create queue failed\n");
	}

	msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);//将结构体内容写入到1234消息队列中

	msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),999,0);//写入之后从队列中获取999类型的数据并存放到结构体的mtext中,如果队列中未出现999类型的数据,则程序阻塞在这里,这里的999需要与写入队列类型数据一致
	printf("return form queue:%s\n",readBuf.mtext);
	
	return 0;
}

运行get.c,创建并打开键值为1234的消息队列,但此时表现为堵塞状态,因为队列里没有888类型的数据

运行send.c,创建并打开键值为1234的消息队列,往队列里写入888类型的数据,此时接收端会接受到写入端写入消息队列的数据并将其读取,同时让接收端往队列里写入999类型的数据,让写入段接受999类型的数据并读取

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值