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.rhkb.cn/news/298122.html

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

相关文章

Vue项目登录页实现获取短信验证码的功能

之前我们写过不需要调后端接口就获取验证码的方法,具体看《无需后端接口,用原生js轻松实现验证码》这个文章。现在我们管理后台有个需求,就是登录页面需要获取验证码,用户可以输入验证码后进行登录。效果如下,当我点击获取验证码后能获取短信验证码: 这里在用户点击获取…

win11安装WSL UbuntuTLS

win11安装WSL WSL 简介WSL 1 VS WSL 2先决要求安装方法一键安装通过「控制面板」安装 WSL 基本命令Linux发行版安装Ubuntu初始化相关设置root用户密码网络工具安装安装1panel面板指导 WSl可视化工具问题总结WSL更新命令错误Ubuntu 启动初始化错误未解决问题 WSL 简介 Windows …

Sybase ASE中的char(N)的坑以及与PostgreSQL的对比

1背景 昨天,一朋友向我咨询Sybase ASE中定长字符串类型的行为,说他们的客户反映,同样的char类型的数据,通过jdbc来查,Sybase库不会带空格,而PostgreSQL会带。是不是这样的?他是PostgreSQL的专业大拿,但因为他手头没有现成的Sybase ASE环境,刚好我手上有,便于一试。 …

hive 慢sql 查询

hive 慢sql 查询 查找 hive 执行日志存储路径&#xff08;一般是 hive-audit.log &#xff09; 比如&#xff1a;/var/log/Bigdata/audit/hive/hiveserver/hive-audit.log 解析日志 获取 执行时间 执行 OperationId 执行人 UserNameroot 执行sql 数据分隔符为 \001 并写入 hiv…

vuepress-theme-hope 添加谷歌统计代码

最近做了个网站,从 cloudflare 来看访问量,过去 30 天访问量竟然有 1.32k 给我整懵逼了,我寻思不应该呀,毕竟这个网站内容还在慢慢补充中,也没告诉别人,怎么就这么多访问?搜索了下, cloudflare 还会把爬虫的请求也就算进来,所以数据相对来说就不是很准确 想到了把 Google An…

如何同时安全高效管理多个谷歌账号?

您的业务活动需要多个 Gmail 帐户吗&#xff1f;出海畅游&#xff0c;Gmail账号是少不了的工具之一&#xff0c;可以关联到Twitter、Facebook、Youtube、Chatgpt等等平台&#xff0c;可以说是海外网络的“万能锁”。但是大家都知道&#xff0c;以上这些平台注册多账号如果产生关…

Cisco交换机安全配置

Cisco交换机安全配置 前提 我们以下命令一般都要先进入Config模式 S1> enable S1# conf t S1(config)#端口安全保护 禁用未使用的端口 以关闭fa0/1到fa0/24的端口为例 S1(config)# interface range fa0/1-24 S1(config-if-range)# shutdown缓解MAC地址表攻击 防止CAM…

蓝桥杯刷题第六天(昨天忘记发了)

今天想从不一样的角度来解题&#xff1a;从时间紧张暴力求解到思路阔达直接通过所有案例 暴力方法&#xff1a; 思路第一眼看到这个问题我就想到了第一个思路就是先用两个数组一个存石子数一个存颜色状态&#xff0c;每次遍历一遍看看有没有相邻石子颜色一样且为和最小的。 im…

前端订阅后端推送WebSocket定时任务

0.需求 后端定时向前端看板推送数据&#xff0c;每10秒或者30秒推送一次。 1.前言知识 HTTP协议是一个应用层协议&#xff0c;它的特点是无状态、无连接和单向的。在HTTP协议中&#xff0c;客户端发起请求&#xff0c;服务器则对请求进行响应。这种请求-响应的模式意味着服务器…

Spring-IoC 基于注解

基于xml方法见&#xff1a;http://t.csdnimg.cn/dir8j 注解是代码中的一种特殊标记&#xff0c;可以在编译、类加载和运行时被读取&#xff0c;执行相应的处理&#xff0c;简化 Spring的 XML配置。 格式&#xff1a;注解(属性1"属性值1",...) 可以加在类上…

纯C代码模板

一、快排 void QuickSort(int *a,int left,int right){if(left>right) return;else{int low left,high right;int pivot a[low];while(low<high){while(a[high] > pivot && low < high){high--;}a[low] a[high]; //必须先动a[low]while(a[low] < …

工厂方法模式与抽象工厂模式的深度对比

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自&#xff1a;设计模式深度解析&#xff1a;工厂方法模式与抽象工厂模式的深…

intellij idea 使用git撤销(取消)commit

git撤销(取消) 未 push的 commit Git&#xff0c;选择分支后&#xff0c;右键 Undo Commit &#xff0c;会把这个 commit 撤销。 git撤销(取消) 已经 push 的 commit 备份分支内容&#xff1a; 选中分支&#xff0c; 新建 分支&#xff0c;避免后续因为操作不当&#xff0c;导…

Spring重点知识(个人整理笔记)

目录 1. 为什么要使用 spring&#xff1f; 2. 解释一下什么是 Aop&#xff1f; 3. AOP有哪些实现方式&#xff1f; 4. Spring AOP的实现原理 5. JDK动态代理和CGLIB动态代理的区别&#xff1f; 6. 解释一下什么是 ioc&#xff1f; 7. spring 有哪些主要模块&#xff1f;…

layui框架实战案例(26):layui-carousel轮播组件添加多个Echarts图标的效果

在Layui中&#xff0c;使用layui-carousel轮播组件嵌套Echarts图表来实现多个图表的展示。 css层叠样式表 调整轮播图背景色为白色&#xff1b;调整当个Echarts图表显示loading…状态&#xff1b;同一个DIV轮播项目添加多个Echarts的 .layui-carousel {background-color: #f…

前端路径问题总结

1.相对路径 不以/开头 以当前资源的所在路径为出发点去找目标资源 语法: ./表示当前资源的路径 ../表示当前资源的上一层路径 缺点:不同位置,相对路径写法不同2.绝对路径 以固定的路径作为出发点作为目标资源,和当前资源所在路径没关系 语法:以/开头,不同的项目中,固定的路径…

当前2024阿里云服务器哪个地域价格比较优惠,哪个地域便宜?

目前2024年阿里云服务器地域对比哪个价格更优惠&#xff1f;华北6&#xff08;乌兰察布&#xff09;、华北3&#xff08;张家口&#xff09;、华北1&#xff08;青岛&#xff09;和华南2&#xff08;河源&#xff09;地域更便宜&#xff0c;云服务器吧yunfuwuqiba.com整理阿里云…

Python 网络请求:深入理解Requests库

目录 引言 一、Requests库简介 二、安装与基本使用 三、requests库的特性与优势 四、requests库在实际应用中的案例 1.get请求 2.post请求 3.超时重试 4.headers设置 5.session会话 6.携带cookie​​​​​​​ 7.携带代理​​​​​​​ 8.携带身份认证​​​​​…

SpringBoot学习笔记-S2

1. SpringBoot中的常见注解 RequestBody&#xff1a;使SpringMVC框架可自动读取请求体里面的JSON格式的数据&#xff0c;转换成map类型的集合对象RestController&#xff1a;开发RESTful API 时使用&#xff0c;等价于ResponseBody Controller。RestController和Controller的…

【简单讲解下WebSocket】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…