linux的通信方案(SYSTEM V)
文章目录
- 共享内存(Share Memory)
- 信号队列(Message Queue)
- 信号量(semaphore)
进程间通信的核心理念:让不同的进程看见同一块资源
linux下的通信方案: SYSTEM V
共享内存(Share Memory)
特点:1.共享内存是进程见通信最最快的
2.可以提供较大通信空间
注意:共享内存由于裸露给所有使用者,因此是需要维护的
做法:去申请一块空间,让其映射到对应的不同进程的进程地址空间。
如图:
那么具体是怎么做的呢?
- linux是生成一个特定的key,有key作为表示这块共享内存的唯一标识。
- 不同进程在运行的时候凭借这个key拿到共享内存的shmid(类似于文件管理系统的fd),进行挂接到自己的进程地址空间上。
- 申请的空间是不会自己释放的,要么在程序里面用funtion控制,要么在外部手动释放
-
ipcs -m
-
#查看当前有哪些共享内存
-
ipcrm -m shmid
-
#删除对应的共享内存id
需要用到的系统调用:
shmget #创建共享内存
shmat # 挂接共享内存
shmdt # 取消挂接
shmctl # 操控这块共享内存
unlink # 删除文件
server:
#include "Common.hpp"class Init
{
public:Init(){bool r = MakeFifo();//用管道是为了进程进行时,具备一定顺序性。if (!r)return;key_t key = GetKey();shmid = CreatShm(key);std::cout << "shmid:" << shmid << "\n";// sleep(5);std::cout << "开始将shm映射到进程地址空间\n";s = (char *)shmat(shmid, nullptr, 0);fd = open(filename.c_str(), O_RDONLY);}~Init(){close(fd);std::cout << "将shm从进程地址空间移除\n";shmdt(s);std::cout << "将共享内存从操作系统中释放\n";shmctl(shmid, IPC_RMID, nullptr);unlink(filename.c_str());}int FileDirection(){return fd;}const char *ShnPtr(){return s;}private:int shmid;int fd;char *s;
};int main()
{Init init;// struct shmid_ds ds;// std::cout<<std::hex<<ds.shm_perm.__key<<"\n";// std::cout<<ds.shm_nattch<<"\n";while (true){int code = 0;ssize_t n = read(init.FileDirection(), &code, sizeof(code));if (n > 0){std::cout << "共享读取:" << init.ShnPtr() << "\n";}else if (n == 0){break;}else{std::cerr << "读取错误,错误码:" << errno << "\n";}}return 0;
}
client
#include "Common.hpp"int main()
{key_t key = GetKey();int shmid = CreatShmHelper(key, IPC_CREAT | 0644);char *s = static_cast<char *>(shmat(shmid, nullptr, 0));std::cout << "attach shm done\n";int fd = open(filename.c_str(), O_WRONLY);for (int c = 0; c < 26; c++){s[c] = c + 'a';std::cout << "write:" << (char)c + 'a' << "done\n";sleep(1);int code = 1;write(fd, (char *)&code, sizeof(code));}// sleep(5);std::cout << "dettach shm done\n";shmdt(s);close(fd);return 0;
}
.h
#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>const std::string pathname = "./Common.hpp";//这里选择一起的头文件作为生成Key的路径文件即可
const int proj_id = 0x234;
const int size = 4096;
const std::string filename = "fifo";
key_t GetKey()
{key_t key = ftok(pathname.c_str(), proj_id);if (key < 0){std::cerr << "errno:" << errno << ",errnostring:" << std::strerror(errno) << std::endl;exit(-1);}return key;
}int CreatShmHelper(key_t key, int flag)
{int shmid = shmget(key, size, flag); //共享内存也有权限也是需要设置的// EXCL保证创建时如果存在就会失败if (shmid < 0){std::cerr << "errno:" << errno << ",errnostring:" << std::strerror(errno) << std::endl;exit(2);}return shmid;
}int CreatShm(key_t key)
{return shmget(key, size, IPC_CREAT | IPC_EXCL | 0644); //共享内存也有权限也是需要设置的
}int GetShm(key_t key)
{return shmget(key, size, IPC_CREAT); //共享内存也有权限也是需要设置的
}//为1创建成功
bool MakeFifo()
{int n = mkfifo(filename.c_str(), 0666);if (n < 0){std::cerr << "errno:" << errno << ",errstring" << strerror(errno) << std::endl;return 0;}std::cout << "mkfifo success..." << std::endl;return 1;
}
信号队列(Message Queue)
基于SYSTEM V的还有对应的信号队列(Message Queue),信号量
下面展示下Message Queue的简单使用代码。
基本的系统调用函数,在下面代码中有,具体使用可以通过man手册查询。
#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <sys/msg.h>
key_t GetKey()
{key_t key = ftok(pathname.c_str(), proj_id);if (key < 0){std::cerr << "errno:" << errno << ",errnostring:" << std::strerror(errno) << std::endl;exit(-1);}return key;
}//消息队列也是存在于内核之中,不手动关闭的生命周期和内核一起int main()
{key_t key = GetKey();int msgid = msgget(key,IPC_CREAT |IPC_EXCL);std::cout<<"msgid:"<<msgid<<'\n';struct msqid_ds ds;std::cout<<ds.__msg_cbytes<<'\n';std::cout<<ds.msg_perm.__key<<'\n';//用msgsend来发送消息//用msgrcv来接受消息msgctl(msgid,IPC_RMID,nullptr);//也可以 ipcrm -q msgid 在bash删除return 0;}
信号量(semaphore)
前置知识:
- 公共资源:多个执行流看见的同一份资源
- 多个执行流访问同一份资源,就存在并发访问
- 为了解决并发访问公共资源的问题,导致的数据不一致、脏读等问题,需要保护资源
- 因此引发出互斥和同步
- 互斥:同一时刻,只能有一个执行流访问资源,加锁完成
- 同步:多个执行流按照预定的先后次序来访问公共资源
- 被保护起来的资源,称为临界资源
- 访问临界资源的执行流(或者代码),称为临界区
分析: - 本质是个计数器
- 当进程需要访问公共资源,先获取信号量,再去访问资源。(相当于信号量是获取资源的凭证,有了信号量,就一定会有资源)没获取信号量的进程,就阻塞等待。
- 信号量如果被获取了,就没了,没被获取,就全部都在。是只有两种状态,二元性的。因此由此二元性,完成了互斥的功能
- 不同的进程也需要看到同一份信号量,因此信号量也被纳入IPC体系,也就是说,信号量由操作系统提供
- 我们知道SYSTEM V的资源是可以看见的,但是信号量是原子的(atomic,不可在分的),即使被进程竞争的访问,也只会出现要么获取了,要么没获取信号量。不会出现获取半个的情况。这种原子的获取操作称之为P操作。相对应原子的释放,称之为V操作。
信号量系统调用
semget
semctl
semop
linux内核看SYSTEM V设计的共享内存等通信方式
一般来说:
- 内核里面有一个ipc_id_ary,其是一个柔性数组,存储了一个size表示大小和指针数组,size表示指针数组的个数
- 这个指针数组所存的指针类型是 **kern_ipc_perm***的指针类型
- 由SYSTEM V标准下设计出来的共享内存,信号队列等,内核里面都是由一个自己类型的结构体去管理的(例如:msg_queue,就是管理信号队列的结构体,Shmid_Kernel, 就是管理共享内存的结构体)
- 而这些结构体的第一个元素,都被设计成相似的结构体(信号队列是:q_perm,共享内存是:shm_perm),这些结构体所包含的元素类型,其实和 kern_ipc_perm的结构体元素类型是一样的。
- 这就使得我们存储kern_ipc_perm的指针,即使存了msg_queue的结构体指针,只需要通过强制类型转换,也是可以访问msg_queue结构体
- 这样对SYSYTEM V设计下的共享内存,信号队列等可以统一管理
上面这种内核的设计:实际就是利用了C语言的特点,实现了多态,有种通过父类指针访问子类的类似
相关文章:

linux的通信方案(SYSTEM V)
文章目录 共享内存(Share Memory)信号队列(Message Queue)信号量(semaphore) 进程间通信的核心理念:让不同的进程看见同一块资源 linux下的通信方案: SYSTEM V 共享内存(Share Memory) 特点:1.共享内存是进程见通信最…...

VUE 入门及应用 ( 路由 router )
6.前端路由 router Vue Router | Vue.js 的官方路由 (vuejs.org) 官方地址 : https://router.vuejs.org/zh/ 6.1.基本配置 6.1.0.准备 MyPage.vue 创建 用于测试 vue文件 ../views/MyPage.vue <template><div><h1>MyPage</h1></div> </…...

SpringBoot集成RocketMQ
RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件,前身是MetaQ,是阿里参考Kafka特点研发的一个队列模型的消息中间件,后开源给apache基金会成为了apache的顶级开源项目,具有高性能、高可靠、高实时、分布式特点。 环境搭…...

【Web】关于FastJson反序列化开始前的那些前置知识
目录 FastJson介绍 FJ序列化与反序列化方法 关于反序列化三种方式的关系与区别 FastJson反序列化漏洞原理通识 关于getter&setter FastJson介绍 FastJson(快速JSON)是一个Java语言编写的高性能、功能丰富且易于使用的JSON解析和序列化库。它由…...

工业镜头的重要参数之视场、放大倍率、芯片尺寸--51camera
今天来简单介绍下工业镜头中常用的参数中的三个: 1、视场 视场(FOV)也称视野,是指能被视觉系统观察到的物方可视范围。 对于镜头而言,可观察到的视场跟镜头放大倍率及相机芯片选择有关。因此需要根据被观察物体的尺寸ÿ…...

基于java springboot+redis网上水果超市商城设计和实现以及文档
基于java springbootredis网上水果超市商城设计和实现以及文档 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留…...

3. 在Go语言项目中使用Zap日志库
文章目录 一、介绍二、 默认的Go Logger1. 实现Go Logger2. 设置Logger3. 使用Logger4. Logger的运行5. Go Logger的优势和劣势 三、Uber-go Zap1. 为什么选择Uber-go zap2. 安装3. 配置Zap Logger4. 定制logger4.1 将日志写入文件而不是终端4.2 将JSON Encoder更改为普通的Log…...

想要节省成本,哪个品牌的https证书值得考虑?
为了确保网站数据传输安全,启用HTTPS加密是关键步骤。在众多SSL证书供应商中,如何找到价格合理且品质优良的HTTPS加密证书呢?本文将探讨这个问题,并重点关注具有高性价比优势的沃通CA。 沃通CA作为业内知名的SSL证书服务商&#x…...

R语言及其开发环境简介
R语言及其开发环境简介 R 语言历史 R 语言来自 S 语言,是 S 语言的一个变种。S语言由贝尔实验室研究开发,著名的 C 语言、Unix 系统也是贝尔实验室开发的。R 属于 GNU 开源软件,最初发布于1997年,实现了与 S 语言基本相同的功能…...

部署DNS解析服务
一、安装软件,关闭防火墙,启动服务 1.yum install -y bind bind-utils bind-chroot 2.systemctl stop firewalld && setenforce 0 3.systemctl start named 二、工作目录 /var/named/chroot/etc #存放主配置文件 /var/named/chroot/var/n…...

2024新算法:鹅算法优化VMD参数,五种适应度函数任意切换,最小包络熵、样本熵、信息熵、排列熵、排列熵/互信息熵...
本期采用鹅算法优化一下VMD参数。利用MATLAB官方自带的VMD函数。 替换为官方自带的VMD函数后,寻优速度真的大幅度提升!数据量大的不妨都试试这个官方的VMD函数。当然要下载2020a以上的MATLAB才可以哦! 同样以西储大学数据集为例,选…...

自定义注解校验
在日常开发中经常会用到String类型的数据当作数值进行映射,势必会做出数值范围的校验,可以通过自定义注解的办法简化代码实现,减少冗余代码。 Target({ElementType.FIELD}) Retention(RetentionPolicy.RUNTIME) Constraint(validatedBy St…...

由数据范围反推算法复杂度以及算法内容
一般ACM或者笔试题的时间限制是1秒或2秒。 在这种情况下,C代码中的操作次数控制在 1 0 7 ∼ 1 0 8 10^7\sim10^8 107∼108为最佳。 下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择: n ≤ 30 n\leq30 n≤30,指数级别…...

js监听F11触发全屏事件
当用户使用 F11 键进行浏览器全屏时,由于此时并非通过浏览器提供的 Fullscreen API 进入全屏模式,因此无法通过 fullscreenchange 事件来监听全屏状态的变化。在这种情况下,可以通过监听 resize 事件来检测浏览器窗口大小的变化,从…...

Seata 2.x 系列【1】专栏导读
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列Seata 版本 2.0.0 源码地址:https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 背景2. 简介3. 适用人群4. 环境及版本5. 文章导航5…...

fly-barrage 前端弹幕库(3):滚动弹幕的设计与实现
项目官网地址:https://fly-barrage.netlify.app/; 👑🐋🎉如果感觉项目还不错的话,还请点下 star 🌟🌟🌟。 Gitee:https://gitee.com/fei_fei27/fly-barrage&a…...

Mysql面试总结
基础 1. 数据库的三范式是什么? 第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。第二范式:要求实体的属性完全依赖于主关键字。所谓完全 依赖是指不能存在仅依赖主关键字一部分的属性。第三范式&…...

【深圳五兴科技】Java后端面经
本文目录 写在前面试题总览1、java集合2、创建线程的方式3、对spring的理解4、Spring Boot 和传统 Spring 框架的一些区别5、springboot如何解决循环依赖6、对mybatis的理解7、缓存三兄弟8、接口响应慢的处理思路9、http的状态码 写在前面 关于这个专栏: 本专栏记录…...

画图(ccf201409-2)解题思路
解题思路 填充100*100二维数组,范围内的元素修改成1,最后累积求和。...

蓝桥杯刷题(一)
一、 import os import sys def dps(s):dp [0] * len(s)dp[0] ord(s[0]) - 96if len(s) 1:return dp[-1]dp[1] max(ord(s[0]) - 96, ord(s[1]) - 96)for i in range(2, len(s)):dp[i] max(dp[i - 1], dp[i - 2] (ord(s[i])) - 96)return dp[-1] s input() print(dps(s))…...

设计模式:策略模式 ⑥
一、策略模式思想 简介 策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。…...

数据结构从入门到精通——顺序表
顺序表 前言一、线性表二、顺序表2.1概念及结构2.2 接口实现2.3 数组相关面试题2.4 顺序表的问题及思考 三、顺序表具体实现代码顺序表的初始化顺序表的销毁顺序表的打印顺序表的增容顺序表的头部/尾部插入顺序表的头部/尾部删除指定位置之前插入数据和删除指定位置数据顺序表元…...

001-CSS-水平垂直居中布局
水平垂直居中布局 方案一:弹性盒子布局方案二:绝对定位 transform方案三:margin 绝对定位,四个方向为零方案四:绝对定位 margin方案五:绝对定位 calc 方案一:弹性盒子布局 💡 T…...

【[STM32]标准库-自定义BootLoader】
[STM32]标准库-自定义BootLoader BootloaderBootloader的实现BOOTloader工程APP工程 Bootloader bootloader其实就是一段启动程序,它在芯片启动的时候最先被执行,可以用来做一些硬件的初始化或者用作固件热更新,当初始化完成之后跳转到对应的…...

Spring Boot项目中不使用@RequestMapping相关注解,如何动态发布自定义URL路径
一、前言 在Spring Boot项目开发过程中,对于接口API发布URL访问路径,一般都是在类上标识RestController或者Controller注解,然后在方法上标识RequestMapping相关注解,比如:PostMapping、GetMapping注解,通…...

Vue中有哪些优化性能的方法?
Vue是一款流行的JavaScript框架,用于构建交互性强的Web应用程序。在前端开发中,性能优化是一个至关重要的方面,尤其是当应用程序规模变大时。Vue提供了许多优化性能的方法,可以帮助开发人员提升应用程序的性能,从而提升…...

Python pandas遍历行数据的2种方法
背景 pandas在数据处理过程中,除了对整列字段进行处理之外,有时还需求对每一行进行遍历,来处理每行的数据。本篇文章介绍 2 种方法,来遍历pandas 的行数据 小编环境 import sysprint(python 版本:,sys.version.spli…...

Spring之@Transactional源码解析
前言 我们在日常开发的时候经常会用到组合注解,比如:EnableTransactionManagement Transactional、EnableAsync Async、EnableAspectJAutoProxy Aspect。今天我们就来抽丝剥茧,揭开Transactional注解的神秘面纱 EnableTransactionManagement注解的作用 当我们看到类似Ena…...

第三届国际亲子游泳学术峰会,麒小佑为亲游行业提供健康解决方案
第三届国际亲子游泳学术峰会大合影 2024年2月26—28日,第三届国际亲子游泳学术峰会在中国青岛成功召开。 第三届国际亲子游泳学术峰会是中国婴幼游泳行业最高标准的学术性会议,由亲游圈主办,旨在为本行业搭建一个高端圈层,帮助机…...

Python光速入门 - Flask轻量级框架
FlASK是一个轻量级的WSGI Web应用程序框架,Flask的核心包括Werkzeug工具箱和Jinja2模板引擎,它没有默认使用的数据库或窗体验证工具,这意味着用户可以根据自己的需求选择不同的数据库和验证工具。Flask的设计理念是保持核心简单,…...