百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Linux进程间通信——消息队列 linux 消息队列可以被多少进程访问

liebian365 2024-11-03 15:46 5 浏览 0 评论

概念

什么是消息队列?

  • 消息队列亦称报文队列,也叫做信箱。是Linux的一种通信机制,这种通信机制传递的数据具有某种结构,而不是简单的字节流。
  • 消息队列的本质其实是一个内核提供的链表,内核基于这个链表,实现了一个数据结构
  • 向消息队列中写数据,实际上是向这个数据结构中插入一个新结点;从消息队列汇总读数据,实际上是从这个数据结构中删除一个结点
  • 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
  • 消息队列也有管道一样的不足,就是每个数据块的最大长度是有上限的,系统上全体队列的最大总长度也有一个上限

队列工作机制



用户消息缓冲区

无论发送进程还是接收进程,都需要在进程空间中用消息缓冲区来暂存消息。该消息缓冲区的结构定义如下

struct msgbuf {
	long mtype;         /* 消息的类型 */
	char mtext[1];      /* 消息正文 */
};
  • 可通过mtype区分数据类型,同过判断mtype,是否为需要接收的数据
  • mtext[]为存放消息正文的数组,可以根据消息的大小定义该数组的长度

创建消息队列

通过msgget创建消息队列
函数原型如下

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

int msgget(key_t key, int msgflg);

参数

  • key: 某个消息队列的名字
  • msgflg:由九个权限标志构成,用法和创建文件时使用的mode模式标志是一样的,这里举两个来说明
IPC_CREAT
	如果消息队列对象不存在,则创建之,否则则进行打开操作
IPC_EXCL
	如果消息对象不存在则创建之,否则产生一个错误并返回

返回值

  • 成功msgget将返回一个非负整数,即该消息队列的标识码;
  • 失败则返回“-1”

那么如何获取key值?

  • 通过宏定义key值
  • 通过ftok函数生成key值,这里就不具体介绍ftok函数用法

Linuxc/c++服务器开发高阶视频,电子书学习资料后台私信【架构】获取


添加信息到消息队列

向消息队列中添加数据,使用到的是msgsnd()函数
函数原型如下

int  msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);

参数

  • msgid: 由msgget函数返回的消息队列标识码
  • msg_ptr:是一个指针,指针指向准备发送的消息,
  • msg_sz:是msg_ptr指向的消息长度,消息缓冲区结构体中mtext的大小,不包括数据的类型
  • msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
    如:
    msgflg = IPC_NOWAIT 表示队列满不等待,返回EAGAIN错误

返回值

  • 成功返回0
  • 失败则返回-1

从消息队列中读取消息

从消息队列中读取消息,我们使用msgrcv()函数,
函数原型如下

int  msgrcv(int msgid, void *msg_ptr, size_t msgsz,
		 long int msgtype, int msgflg);

参数

  • msgid: 由msgget函数返回的消息队列标识码
  • msg_ptr:是一个指针,指针指向准备接收的消息,
  • msgsz:是msg_ptr指向的消息长度,消息缓冲区结构体中mtext的大小,不包括数据的类型
  • msgtype:它可以实现接收优先级的简单形式
    msgtype=0返回队列第一条信息
    msgtype>0返回队列第一条类型等于msgtype的消息 
    msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息
  • msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事
    msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
    msgflg=MSG_NOERROR,消息大小超过msgsz时被截断

注意

msgtype>0且msgflg=MSC_EXCEPT,接收类型不等于msgtype的第一条消息

返回值

  • 成功返回实际放到接收缓冲区里去的字符个数
  • 失败,则返回-1

消息队列的控制函数

函数原型

int  msgctl(int msqid, int command, strcut msqid_ds *buf);

参数

  • msqid: 由msgget函数返回的消息队列标识码
  • command:是将要采取的动作,(有三个可取值)分别如下


注意:若选择删除队列,第三个参数传NULL
返回值
如果操作成功,返回“0”;如果失败,则返回“-1”

查看消息队列

  • 查看消息队列
    ipcs -q 命令查看已经创建的消息队列,包括他的key值信息,id信息,拥有者信息,文件权限信息,已使用的字节数,和消息条数。
  • ipcrm -Q加消息队列的key值,或来删除一个消息队列。

举一个例子,父进程写消息(先写发送的数据类型,再写数据),子进程收消息类型为1的消息

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

#define MSGKEY 123

//消息的数据结构是以一个长整型成员变量开始的结构体
struct msgstru
{
	long msgtype;
	char msgtext[2048];
};

int main()
{
	struct msgstru msgs;
	char str[256];
	int msg_type;
	int ret_value;
	int msqid;
	int pid;

	//检查消息队列是否存在
	msqid = msgget(MSGKEY, IPC_EXCL);//(键名,权限)
	if (msqid < 0)
	{
		//创建消息队列
		msqid = msgget(MSGKEY, IPC_CREAT | 0666);
		if (msqid <0)
		{
			printf("failed to create msq | errno=%d [%s]\n", errno, strerror(errno));
			exit(-1);
		}
	}

	pid = fork();//创建子进程
	if (pid > 0)
	{
		//父进程
		while (1)
		{
			printf("input message type:\n");//输入消息类型
			scanf("%d", &msg_type);
			if (msg_type == 0)
				break;

			printf("input message to be sent:\n");//输入消息信息
			scanf("%s", str);

			msgs.msgtype = msg_type;
			strcpy(msgs.msgtext, str);

			//发送消息队列(sizeof消息的长度,而不是整个结构体的长度)
			ret_value = msgsnd(msqid, &msgs, sizeof(msgs.msgtext), IPC_NOWAIT);
			if (ret_value < 0)
			{
				printf("msgsnd() write msg failed,errno=%d[%s]\n", errno, strerror(errno));
				exit(-1);
			}
		}
	}
	else if (pid == 0)
	{
		//子进程
		while (1)
		{
			msg_type = 1;//接收的消息类型为1
			msgs.msgtype = msg_type;

			//发送消息队列(sizeof消息的长度,而不是整个结构体的长度)
			ret_value = msgrcv(msqid, &msgs, sizeof(msgs.msgtext), msgs.msgtype, IPC_NOWAIT);
			if (ret_value > 0)
			{
				printf("read msg:%s\n", msgs.msgtext);
			}
		}
	}
	else
	{
		printf("fork error\n");
		//删除消息队列
		msgctl(msqid, IPC_RMID, 0);
		exit(1);
	}

	return 0;
}

运行结果

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: