0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux下进程通讯消息队列

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-08-19 19:56 次阅读

Linux下进程通讯消息队列

 MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是message 而已。MQ 是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信

消息队列与 FIFO 很相似,都是一个队列结构,都可以有多个进程往队列里面写信息,多个进程从队列中读取信息。

1.查看消息队列命令

  1.查看消息队列:ipcs -q

[wbyq@wbyq ~]$ ipcs -q

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      
0xb8104ad9 1          wbyq       644        0            0           
0xd2350093 2          wbyq       666        208          2  

  2.查看消息队列限制信息:ipcs -lq

[wbyq@wbyq ~]$ ipcs -lq

---------- 消息限制 -----------
系统最大队列数量 = 32000
最大消息尺寸 (字节) = 8192
默认的队列最大尺寸 (字节) = 16384

  3.查看消息队列详细信息:ipcs -q -i

[wbyq@wbyq ~]$ ipcs -q -i 2

消息队列 msqid=2
uid=1000	gid=1000	cuid=1000	cgid=1000	模式=0666
cbytes=208	qbytes=16384	qnum=2	lspid=10177	lrpid=10175
发送时间=Thu Apr 28 11:56:08 2022  
接收时间=Thu Apr 28 11:56:08 2022  
更改时间=Thu Apr 28 11:49:04 2022  

  4.创建消息队列:ipcmk -Q

[wbyq@wbyq ~]$ ipcmk -Q
消息队列 id:4
[wbyq@wbyq ~]$ ipcs -q

--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      
0xb8104ad9 1          wbyq       644        0            0           
0xd2350093 2          wbyq       666        208          2           
0x05ae2c01 4          wbyq       644        0            0        

5.删除信号量:ipcrm -q

[wbyq@wbyq ~]$ ipcrm -q 4
[wbyq@wbyq ~]$ ipcs -q
--------- 消息队列 -----------
键        msqid      拥有者  权限     已用字节数 消息      
0xb8104ad9 1          wbyq       644        0            0           
0xd2350093 2          wbyq       666        208          2    

2.相关函数

#include 
#include 
#include 
int msgget(key_t key, int msgflg);
函数功能:创建消息队列
形参:key 键值,ftok产生
     msgflg 标志 IPC_CREAT|0666
返回值:失败返回-1,成功返回msqid
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
函数功能: 将消息添加到队列中
形参:msqid msgget函数返回值
   msgp 消息内容数据,一般以结构体类型填充
      struct msgbuf {
            long mtype; /* 消息类型, 必须 > 0 */
            char mtext[1]; /消息数据/
            };
      注意:struct msgbuf必须自己重写,第一个参数long mtype必须指定,且>0,其他类型自定义
   msgsz 消息字节数,大小为:sizeof(struct msgbuf)-sizeof(mtype);
   msgflg 0当队列满时阻塞,直到消息写入成功
      IPC_NOWAIT 当队列满时不阻塞,立刻返回
      IPC_NOERROR 若发送的消息大于 size 字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。
返回值:成功返回0,失败返回-1;
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
函数功能:从队列中取出消息
形参:msqid msgget函数返回值
   msgp 存放读取到的消息内容
   msgsz 消息字节数,大小为:sizeof(struct msgbuf)-sizeof(mtype);
   msgtyp 消息类型:
       >0 接收对列中的第 1 个类型等于 msgtyp 的消息
       ==0 取出消息队列中的第一条消息
       <0 接收其类型小于或等于 msgtyp 绝对值的第 1 个最低类型消息
   msgflg 0 当队列空时阻塞,或者消息类型不匹配时阻塞
       IPC_NOWAIT 不阻塞,立刻返回
       IPC_NOERROR 若发送的消息大于 size 字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。
返回值:成功返回读取的字节数,失败返回-1;
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
函数功能:控制函数
形参:msqid msgget函数返回值
   cmd 通常为 IPC_RMID 表示删除消息队列。
当删除消息队列时,则buf填NULL即可;

3.示例

  (1)创建消息队列,添加消息到队列

#include 
#include 
#include 
#include 
#include 
#include 
#include 
struct msgbuf
{
	long mtype;//消息类型,必须>0
	int cnt;
	char buff[100];
};
int main(int argc,char *argv[])
{
	if(argc!=4)
	{
		printf("格式:./app <消息类型> <消息数据> <消息内容>\n");
		return 0;
	}
    key_t key=ftok("msgsnd.c", 1234);//生成键值
	if(key==-1)
	{
		printf("生成键值失败err=%s\n",strerror(errno));
		return 0;
	}
	printf("key=%#x\n",key);
	int msqid=msgget(key,IPC_CREAT|0666);//创建消息队列
	if(msqid==-1)
	{
		printf("创建消息队列失败err=%s\n",strerror(errno));
		return 0;
	}
	printf("msqid=%d\n",msqid);
	struct msgbuf msg;
	msg.mtype=atoi(argv[1]);//消息类型
	msg.cnt=atoi(argv[2]);//消息数据
	strcpy(msg.buff,argv[3]);//消息内容
	int msg_size=sizeof(msg)-sizeof(long);//消息大小,总大小-消息类型大小
	/*添加消息到队列*/
	int size=msgsnd(msqid,&msg,msg_size,0);
	if(size==-1)
	{
		printf("写入消息失败err=%s\n",strerror(errno));
	}
	else printf("消息写入成功\n");
	return 0;
}  

  (2)从队列中取消息

#include 
#include 
#include 
#include 
#include 
#include 
#include 
struct msgbuf
{
	long mtype;//消息类型,必须>0
	int cnt;
	char buff[100];
};
int main(int argc,char *argv[])
{
	if(argc!=2)
	{
		printf("格式:./app <消息类型>\n");
		return 0;
	}
    key_t key=ftok("msgsnd.c", 1234);//生成键值
	if(key==-1)
	{
		printf("生成键值失败err=%s\n",strerror(errno));
		return 0;
	}
	printf("key=%#x\n",key);
	int msqid=msgget(key,IPC_CREAT|0666);//创建消息队列
	if(msqid==-1)
	{
		printf("创建消息队列失败err=%s\n",strerror(errno));
		return 0;
	}
	printf("msqid=%d\n",msqid);
	struct msgbuf msg;
	int msg_size=sizeof(msg)-sizeof(long);//消息大小
	long msgtyp=atoi(argv[1]);//要写读取的消息类型
	//从消息队列中取数据
	ssize_t size=msgrcv(msqid,&msg,msg_size,msgtyp,0);
	if(size==-1)
	{
		printf("读取消息失败err=%s\n",strerror(errno));
	}
	else 
	{
		printf("------------读取消息成功size:%ld----------------\n",size);
		printf("\tmtype=%ld\n",msg.mtype);
		printf("\tcnt=%d\n",msg.cnt);
		printf("\tbuff=%s\n",msg.buff);
	}
	return 0;
}  

  (3)运行效果

pYYBAGL_eXuABxWmAAeJ5O7XsAY981.png#pic_center


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11221

    浏览量

    208883
  • IPC
    IPC
    +关注

    关注

    3

    文章

    345

    浏览量

    51816
  • 进程
    +关注

    关注

    0

    文章

    201

    浏览量

    13947
收藏 人收藏

    评论

    相关推荐

    深入Linux进程管理:提升效率与稳定性的关键方法

    目录 Linux进程管理 8.1 IO负载 8.2 实时进程监控 5.1 作业与会话 5.2 作业分类 4.1 ps 4.2pstree 4.3pgrep 4.4pidof 4.5 vmstat
    的头像 发表于 11-22 11:05 55次阅读
    深入<b class='flag-5'>Linux</b><b class='flag-5'>进程</b>管理:提升效率与稳定性的关键方法

    一文搞懂Linux进程的睡眠和唤醒

    ): 进程在等待某个条件满足(如I/O操作),可以被信号唤醒。 Linux通过内核提供的系统调用来控制进程的睡眠。常用的系统调用有: sleep(): 使进程暂停指定的秒数。 usl
    发表于 11-04 15:15

    Linux用户身份与进程权限详解

    在学习 Linux 系统权限相关的主题时,我们首先关注的基本都是文件的 ugo 权限。ugo 权限信息是文件的属性,它指明了用户与文件之间的关系。但是真正操作文件的却是进程,也就是说用户所拥有的文件
    的头像 发表于 10-23 11:41 239次阅读
    <b class='flag-5'>Linux</b>用户身份与<b class='flag-5'>进程</b>权限详解

    嵌入式环形队列与消息队列的实现原理

    嵌入式环形队列,也称为环形缓冲区或循环队列,是一种先进先出(FIFO)的数据结构,用于在固定大小的存储区域中高效地存储和访问数据。其主要特点包括固定大小的数组和两个指针(头指针和尾指针),分别指向队列的起始位置和结束位置。
    的头像 发表于 09-02 15:29 323次阅读

    深入探讨Linux进程调度器

    Linux操作系统作为一个开源且广泛应用的操作系统,其内核设计包含了许多核心功能,而进程调度器(Scheduler)就是其中一个至关重要的模块。进程调度器负责决定在任何给定的时刻哪个进程
    的头像 发表于 08-13 13:36 890次阅读
    深入探讨<b class='flag-5'>Linux</b>的<b class='flag-5'>进程</b>调度器

    进程间通信的消息队列介绍

    消息队列是一种非常常见的进程间通信方式。
    的头像 发表于 04-08 17:27 284次阅读

    linux查询进程占用的内存方法有哪些?

    linux查询进程占用的内存方法
    发表于 04-08 06:03

    如何使用linuxgdb来调试python程序

    如何使用linuxgdb来调试python程序  在Linux,可以使用GDB(GNU调试器)来调试Python程序。GDB是一个强大的调试工具,可以帮助开发者诊断和修复程序中的错
    的头像 发表于 01-31 10:41 2416次阅读

    浅谈Linux进程

    进程和程序的区别: 进程是动态的,程序是静态的 一、进程的创建(fork()函数) int main(){ pid_t pid; pid=fork(); if(pid     >0
    的头像 发表于 01-28 15:54 238次阅读
    浅谈<b class='flag-5'>Linux</b>的<b class='flag-5'>进程</b>

    裸机中环形队列与RTOS中消息队列有何区别呢?

    “环形队列”和“消息队列”在嵌入式领域有应用非常广泛,相信有经验的嵌入式软件工程师对它们都不陌生。
    的头像 发表于 01-26 09:38 684次阅读
    裸机中环形<b class='flag-5'>队列</b>与RTOS中消息<b class='flag-5'>队列</b>有何区别呢?

    labview 队列最前端插入的应用

    起到很多作用。本文将详细介绍LabVIEW队列的应用,特别是在最前端插入数据的情况。 首先,让我们了解LabVIEW队列的基本概念。队列是一种数据结构,允许在一端插入元素,并在另一端
    的头像 发表于 01-08 11:45 1146次阅读

    labview队列有什么实际作用

    LabVIEW队列是一种数据结构,常用于解决多任务并发处理的问题。它被广泛应用于科学研究、工程项目和自动化控制等领域。在LabVIEW中,队列提供了一种高效、方便的方式来处理不同任务之间的数据
    的头像 发表于 01-05 16:42 1496次阅读

    Linux进程、线程和协程的基础概念

    进程是计算机中运行的程序的实例,它是操作系统中最基本的执行单元之一。每个进程都有自己的独立内存空间、系统资源和代码执行流。这意味着一个进程的崩溃通常不会影响其他进程
    的头像 发表于 12-06 09:22 783次阅读

    linux查看weblogic进程

    Linux操作系统中,WebLogic是一种常用的Java应用服务器,用于部署和管理企业级Java应用程序。为了确保WebLogic服务器正常运行,有时我们需要查看WebLogic进程以了解其状态
    的头像 发表于 12-05 16:07 1796次阅读

    Linux进程通信的方法

    进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放。可以认为进程是一个程序的一次执行过程。
    的头像 发表于 11-29 14:45 698次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>下</b><b class='flag-5'>进程</b>通信的方法