Linux多进程通信(4)——消息队列从入门到实战!

Linux多进程通信总结——进程间通信看这一篇足够啦!

1.基本介绍

1)消息队列的本质其实是一个内核提供的链表,内核基于这个链表,实现了一个数据结构,向消息队列中写数据,实际上是向这个数据结构中插入一个新结点;从消息队列汇总读数据,实际上是从这个数据结构中删除一个结点
2)消息队列独立于发送与接收进程,进程终止时,消息队列中的内容不会被删除,所以要记得删除消息队列
3)消息队列可以实现消息的
随机查询
消息不一定要以先进先出的次序读取,也可以按照消息的类型读取
4)Linux环境中,最多有256个消息队列,每个消息最大为8K字节,总大小不能超过16K,否则在send时会阻塞,可以通过更改内核设置的方式更改大小。
image.png

2.API介绍

1)获取消息队列键值

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(char *pathname, char proj);

pathname:路径名,是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
proj:1-255之间的数字
返回值: 生成一个独有的数,失败则返回-1
key 31-24 proj_id 低8位
key 23-16 pathname的st_dev属性的低8位
key 15-0 pathname的st_ino属性的低16位32位组合而成一个int值,就是我们的ftok的返回值了
根据路径名以及数字,合成系统中唯一的Key值

2)创建/获取消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);

key:使用ftok获取到的唯一Key值
msgflag: 和其他的IPC通信一样,IPC_CREAT,如果消息队列对象不存在,则创建之,否则则进行打开操作。IPC_EXCL,如果消息对象不存在则创建之,否则产生一个错误并返回,可同时用IPC_CREATE | 0666
返回值:成功返回消息队列ID,失败则返回-1

3)msgsend发送消息

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

msgid :消息队列ID
msgptr:消息体,消息体的类型是一个结构体

msg_sz: 消息长度 消息体中的消息长度(不是一整个结构体的长度,只是mtext消息数据的长度
msgflag :发送flag 一般设置为0,阻塞式等待(消息队列满),也可以设置为 IPC_NOWAIT,则立刻返回
返回值:成功返回0,失败返回-1
调用成功后,发送内容的一个备份,会被放到消息队列中(这里会有个硬拷贝的过程)

4)msgrecv接收消息

ssize_t msgrcv(int msgid, const void *msgp, size_t msgsz, int msgtype, int msgflag)

msgid:消息队列ID
msgp: 接收到的消息体
msgsz: 接收消息的长度
msgtype :消息类型 ,对应发送时的m_type。
值为0:代表接收一个任意类型的消息
值大于0:获取消息类型为msgtype的第一个消息
值小于0:获取消息类型小于等于msgtype的第一个消息
msgflag :接收的flag一般设置为0,阻塞式等待
msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
msgflg=MSG_NOERROR,消息大小超过msgsz时被截断
msgtype>0且msgflg=MSC_EXCEPT,接收类型不等于msgtype的第一条消息。
返回值:调用成功时,返回接收到消息的字节数,失败返回-1

调用成功时消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息(这里会有个硬拷贝的过程)

5)控制消息队列

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msgid:消息队列id
cmd:控制消息队列的命令选项
IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
IPC_RMID:删除消息队列

其实对于IPC通信来说,这些基本都是通用的~

3.例程

1)服务端

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>#define MSGQ_PATH "./"
#define MSGQ_PRI 100typedef struct {long mtype;char mtext[256];
} MSGQ_T;int iMsgId = 0;int main(int argc, char **argv)
{key_t msgkey = 0;msgkey = ftok(MSGQ_PATH, MSGQ_PRI);if (msgkey == -1){printf("ftok error, pid:%d\n", getpid());return -1;}iMsgId = msgget(msgkey, IPC_CREAT | 0644);if (iMsgId == -1){printf("msgget error, pid:%d\n", getpid());return -1;}printf("msgget success, pid:%d, key:%d, msgid:%d\n", getpid(), msgkey, iMsgId);while (1){MSGQ_T msgBuf = {0};int iMsgType = 0;printf("input message type:\n");//输入消息类型scanf("%d", &iMsgType);if (iMsgType == 0){printf("message type 0, break\n");break;}char acBuf[256] = {0};printf("input message to be send:\n");//输入消息信息scanf("%s", acBuf);msgBuf.mtype = iMsgType;strncpy(msgBuf.mtext, acBuf, sizeof(msgBuf.mtext) - 1);msgsnd(iMsgId, &msgBuf, sizeof(msgBuf), IPC_NOWAIT);printf("msgq:%d, send msgtype:%d, msgtext:%s \n", iMsgId, msgBuf.mtype, msgBuf.mtext);}msgctl(iMsgId, IPC_RMID, NULL);return 0;
}

2)客户端

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>#define MSGQ_PATH "./"
#define MSGQ_PRI 100typedef struct {long mtype;char mtext[256];
} MSGQ_T;int iMsgId = 0;
pthread_t msgqRecvThread = 0; void *msgqRecvThreadTask(void *arg)
{while (1){MSGQ_T msgBuf = {0};int ret = msgrcv(iMsgId, &msgBuf, sizeof(msgBuf), 0, 0);if (ret < 0){return NULL;}printf("msgq:%d, recv msgtype:%d, msgtext:%s, ret:%d \n", iMsgId, msgBuf.mtype, msgBuf.mtext, ret);}return NULL;
}int main(int argc, char **argv)
{key_t msgkey = 0;msgkey = ftok(MSGQ_PATH, MSGQ_PRI);if (msgkey == -1){printf("ftok error, pid:%d\n", getpid());perror("....");return -1;}iMsgId = msgget(msgkey, IPC_CREAT | 0644);if (iMsgId == -1){printf("msgget error, pid:%d\n", getpid());perror("....");return -1;}printf("msgget success, pid:%d, key:%d, msgid:%d\n", getpid(), msgkey, iMsgId);pthread_create(&msgqRecvThread, NULL, msgqRecvThreadTask, NULL);pthread_join(msgqRecvThread, NULL);return 0;
}

可以通过指令分别编译客户端和服务端并执行

gcc server.c -o server -lpthread
gcc client.c -o client -lpthread
./server
./client

在输入框输入消息后,便可以在client观察到消息接收啦
image.png
此时输入ipcs -q后能看到创建的消息队列
image.png
这里我显示有两个消息队列,因为上一个没有用msgctl删除。

当服务端和客户端程序都正常退出时,调用msgctl则会正常删除消息队列,在例程中的server端输入0即可!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/805957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样系统地学习自动化测试?

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 平时的测试工作其实细分一下&#xff0c;大概有三个领域…

C++ 线程库(thread)与锁(mutex)

一.线程库(thread) 1.1 线程类的简单介绍 thread类文档介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如windows和linux下各有自己的接口&#xff0c;这使得代码的可移植性比较差。C11中最重要的特性就是对线程进行支持了&#xff…

操作系统的基础知识:操作系统的特征:并发,共享,虚拟,异步

操作系统的特性&#xff1a; 1.并发 并发:指两个或多个事件在同一时间间隔内发生。这些事件宏观上是同时发生的&#xff0c;但微观上是交替注意&#xff1a;并行:指两个或多个事件在同一时刻同时发生。 操作系统的并发性指计算机系统中“同时”运行着多个程序&#xff0c;这…

graphicLayer.startDraw({开启连续绘制isContinued之后,无法获取连续标绘的坐标数据

摘要&#xff1a;graphicLayer.startDraw({开启连续绘制isContinued之后&#xff0c;无法获取连续标绘的坐标数据的解决方案 问题前景&#xff1a; graphicLayer.startDraw({开启连续绘制isContinued之后&#xff0c;.then()方法只走一次&#xff0c;无法获取连续标绘的所有坐…

【Linux】shell 脚本基础使用

在终端中输入命令可以完成一些常用的操作&#xff0c;但是我们都是一条一条输入命令&#xff0c;比较麻烦&#xff0c;为了解决这个问题&#xff0c;就会涉及到 shell 脚本&#xff0c;它可以将很多条命令放到一个文件里面&#xff0c;然后直接运行这个文件即可。 shell 脚本类…

【3GPP】【核心网】核心网/蜂窝网络重点知识面试题二(超详细)

1. 欢迎大家订阅和关注&#xff0c;3GPP通信协议精讲&#xff08;2G/3G/4G/5G/IMS&#xff09;知识点&#xff0c;专栏会持续更新中.....敬请期待&#xff01; 目录 1. 对于主要的LTE核心网接口&#xff0c;给出运行在该接口上数据的协议栈&#xff0c;并给出协议特征 2. 通常…

Centos7使用docker安装Jenkins(含pipeline脚本语句)

一、下载Jenkins docker pull jenkins/jenkins:lts 二、启动Jenkins docker run \-u root \--rm \-d \-p 8081:8080 \-p 50000:50000 \-v /root/docker/jenkins/var/jenkins_home:/var/jenkins_home \-v /var/run/docker.sock:/var/run/docker.sock \-v /usr/bin/docker:/usr…

番外篇 | YOLOv8改进之引入YOLOv9的ADown模块 | 替换YOLOv8卷积

前言:Hello大家好,我是小哥谈。YOLOv9是一种目标检测算法,而ADown模块是YOLOv9中的一个重要组成部分。ADown模块主要用于特征提取和下采样操作,以便在后续的检测任务中更好地捕捉目标的特征。具体来说,ADown模块是YOLOv9中的一个卷积块,由一系列卷积层和池化层组成。它的…

spring boot —— Spring-Cloud-Zuul(网关服务getway),kafka笔记

一、 引入zuul依赖&#xff1a; org.springframework.cloud spring-cloud-starter-zuul 二、创建应用主类。使用EnableZuulProxy注解开启zuul的API网关服务功能&#xff1a; EnableZuulProxy SpringCloudApplication public class Application { public static void mai…

FPN(Feature Pyramid Network)详解

文章涉及个人理解部分&#xff0c;可能有不准确的地方&#xff0c;敬请指正 0. 概述 FPN&#xff0c;全名Feature Pyramid Networks&#xff0c;中文称为特征金字塔网络。它是2017年cvpr上提出的一种网络&#xff0c;主要解决的是目标检测中的多尺度问题。FPN通过简单的网络连…

第十四届蓝桥杯省赛真题-幸运数

代码及解析: #include <iostream> using namespace std;bool check(int x) {int tmpx,len0;while(tmp){len;tmp/10;}//算位数的方法 if(len%21)return 0;//直接retrun 0 int tlen/2;int ans10,ans20;while(t--){ans1x%10;//加每一位x/10; }while(x){ans2x%10;x/10;}if(…

AOF文件重写

1.2.3.AOF文件重写 因为是记录命令&#xff0c;AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作&#xff0c;但只有最后一次写操作才有意义。通过执行bgrewriteaof命令&#xff0c;可以让AOF文件执行重写功能&#xff0c;用最少的命令达到相同效果。 如图&am…

类和对象(一)

面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 类的…

LeetCode 239. 滑动窗口最大值

滑动窗口最大值 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a;nums [1,3,-1,-3,…

双碳目标下太阳辐射预报模式【WRF-SOLAR】及改进技术在气象、农林、电力等相关领域中的应用

太阳能是一种清洁能源&#xff0c;合理有效开发太阳能资源对减少污染、保护环境以及应对气候变化和能源安全具有非常重要的实际意义&#xff0c;为了实现能源和环境的可持续发展&#xff0c;近年来世界各国都高度重视太阳能资源的开发利用&#xff1b;另外太阳辐射的光谱成分、…

T527 Qt 触摸 ----- TSLIB

一、调试 1、驱动路径 bsp/drivers/input/ctp/gt9xx/gt9xx_ts.c 2、硬件接口 挂载在TWI0下 3、中断复位脚 4、设备树 &twi0 {clock-frequency <400000>;pinctrl-0 <&twi0_pins_default>;pinctrl-1 <&twi0_pins_sleep>;pinctrl-names &quo…

关于ansible的模块 ⑤

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》、《关于Ansible的模块 ③》与《关于Ansible的模块 ④》之后&#xff0c…

Spring Boot 切面的一种的测试方法,java中级开发面试

void afterReturnName() { Assertions.assertEquals(studentController.getNameById(123L).getName(), "测试姓名Yz");} } 但往往切面中的逻辑并非这么简单&#xff0c;在实际的测试中其实我们也完成没有必要关心在切面中到底发生了什么&#xff08;发生了什么应该在…

正则问题【蓝桥杯】/dfs

正则问题 dfs 刚开始用的是栈&#xff0c;没有想到dfs… #include<iostream> #include<stack> using namespace std; string s; int pos; int dfs() {//ans表示到当前位置最多的x数目//num表示暂存的x数目int num0,ans0;while(pos<s.size()){if(s[pos](){pos;…

HarmonyOS实战开发-如何实现文件管理相关的功能。

介绍 本示例主要展示了文件管理相关的功能&#xff0c;使用ohos.multimedia.medialibrary 、ohos.filemanagement.userFileManager 、ohos.fileio 、ohos.file.fs、ohos.app.ability.contextConstant 等接口&#xff0c;实现了增添文件、删除文件、查找指定类型文件文件、复制…