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 = "/home/fuh_cs/Desktop/cpp_learning/linux/ShareMemory/Common.hpp";
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语言的特点,实现了多态,有种通过父类指针访问子类的类似

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

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

相关文章

排序(4)——堆排序

目录 堆排序&#xff08;回顾&#xff09; 基本思路 代码实现 向下调整排序 AdjustDown 建堆排序 时间复杂度 特性总结 堆排序&#xff08;回顾&#xff09; 重点回顾戳&#x1f449;堆排序 基本思路 堆排序(Heapsort)是指利用堆积树&#xff08;堆&#xff09;这种数…

鸿蒙系统开发适配注意事项

鸿蒙操作系统&#xff08;HarmonyOS&#xff09;的软件适配涉及到一些特定的注意事项&#xff0c;以确保应用程序在该操作系统上的正常运行和最佳性能。以下是适配鸿蒙软件时需要注意的一些关键问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的…

MySQL篇—执行计划介绍(第二篇,总共三篇)

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

Python 编辑工具 Jupyter notebook

Jupyter notebook Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。——Jupyter Notebook官方介绍 官网&#xff1a;Project Jupyter | Home Jupyter Notebook 是一个开源的交互式计算环境&#…

网页版图像处理软件开发服务:助您项目在市场竞争中脱颖而出

在当今数字化时代&#xff0c;图像处理在各个行业中扮演着重要的角色&#xff0c;虎克专注于提供定制化的网页版图像处理软件开发服务&#xff0c;为您的项目保驾护航。 1.网页版图像处理软件的定制化需求 1.1行业特定功能 针对不同的业务需求&#xff0c;深入了解行业特点&…

springboot基于web的酒店客房管理系统论文

基于web的酒店客房管理系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了酒店客房管理系统的开发全过程。通过分析酒店客房管理系统管理的不足&#xff0c;创建了一个计算机管理酒店客房管理系统的方案。文…

springboot网站开发-idea开发环境下无法开启调试Debug模式

springboot网站开发-idea开发环境下无法开启调试Debug模式的解决办法。 近期在写后端代码的时候&#xff0c;发现&#xff0c;无法开启调试模式。网上查询了一下资料&#xff0c;发现需要做如下修改即可开启调试模式。 如图所示&#xff0c;把里面的选项&#xff0c;都放弃勾选…

SQLPro Studio:数据库管理的革命性工具 mac版

SQLPro Studio是一款强大的数据库管理和开发工具&#xff0c;它旨在提供高效、便捷和安全的数据库操作体验。无论是数据库管理员、开发人员还是数据分析师&#xff0c;SQLPro Studio都能满足他们在数据库管理、查询、设计和维护方面的需求。 SQLPro Studio mac版软件获取 首先…

B树系列(详解)

目录 一、B-树 二、B树 三、B*树 四、时间复杂度 五、Mysql与B树系列 一、B-树 首先再说B树的性质以及其他的之前&#xff0c;先要说一声&#xff0c;好多人都把这个树叫B减树&#xff0c;其实不是&#xff0c;他就叫B树&#xff0c;至于原因我觉的没必要再这个名字上纠结…

docker 转为docker-compose(composerize 命令)

可以使用Composerize将Docker命令转换为Docker Compose文件。 例如&#xff1a;将docker run命令转换为Docker Compose格式&#xff0c;只需用Composerize运行它&#xff0c;如下所示&#xff1a; composerize docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/…

【JavaSE】异常

异常概述 异常指的是程序在执行的过程中&#xff0c;出现的非正常情况&#xff0c;如果不处理最终会导致JVM的非正常停止。 在Java中&#xff0c;使用不同的类来表示不同的异常&#xff08;正所谓万物皆对象&#xff0c;因此异常也使用类来表示&#xff09;。一旦程序出现某种…

【HTML】HTML基础5(特殊字符)

目录 特殊字符的作用 常用的特殊字符 使用效果 特殊字符的作用 例如 当我在两个文字间打出空格时 <p>“银河护卫队”系列 在漫威电影宇宙中一直是异数般的存在&#xff0c;不仅因为影片主角是一群反英雄&#xff0c;<strong>与超级英雄相比显得格格不入<…

LeetCode 刷题 [C++] 第347题.前 K 个高频元素

题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 题目分析 据题意可知&#xff0c;我们需要先遍历整个数组&#xff0c;并统计每个数字出现的次数&#xff0c;保存在哈希表中&#xff1b;对元素…

synchrosized 的可重入特性、死锁、哲学家就餐问题以及解决死锁的方法等干货

文章目录 &#x1f490;synchrosized的可重入特性关于死锁&#xff1a;哲学家就餐问题&#x1f4a1;如何避免/解决死锁 &#x1f490;synchrosized的可重入特性 可重入特性&#xff1a;当一个线程针对一个对象同时加锁多次&#xff0c;不会构成死锁&#xff0c;这样的特性称为…

前端学习第一天-html基础

达标要求 网页的形成过程 常用的浏览器及常见的浏览器内核 web 标准三层组成 什么是HTML 熟练掌握HTML文档结构 熟练掌握HTML常用标签 1. 初识web前端 Web前端是创建Web页面或App等前端界面呈现给用户的过程。 Web前端开发是从网页制作演变而来&#xff0c;早期网站主…

sklearn.preprocessing.RobustScaler(解释和原理,分位数,四分位差)

提示&#xff1a;sklearn.preprocessing.RobustScaler&#xff08;解释和原理&#xff0c;分位数&#xff0c;四分位差&#xff09; 文章目录 [TOC](文章目录) 一、RobustScaler 是什么&#xff1f;二、代码1.代码2.输出结果 总结 提示&#xff1a;以下是本篇文章正文内容&…

ELK学习

ELK 一、ELK介绍 &#x1f604; “ELK”是三个开源项目的首字母缩写&#xff0c;这三个项目分别是&#xff1a;Elasticsearch、Logstash 和 Kibana。Elasticsearch 是一个搜索和分析引擎。Logstash 是服务器端数据处理管道&#xff0c;能够同时从多个来源采集数据&#xff0…

网络编程(IP、端口、协议、UDP、TCP)【详解】

目录 1.什么是网络编程&#xff1f; 2.基本的通信架构 3.网络通信三要素 4.UDP通信-快速入门 5.UDP通信-多发多收 6.TCP通信-快速入门 7.TCP通信-多发多收 8.TCP通信-同时接收多个客户端 9.TCP通信-综合案例 1.什么是网络编程&#xff1f; 网络编程是可以让设…

网络安全-appcms-master

一、环境 gethub上面自己找appcms-master 二、开始闯关 原理&#xff1a;在评论的时候提交可以提交到管理员列表去&#xff0c;管理员一看cookie和地址就被盗走了 点进去软件后会发现提交按钮 随便提交一下看看 放到div标签里面是不是有可能可以做&#xff0c;看看后台吧 那…

VUE CLI3项目搭建 ESLint配置

VUE项目框架配置 一、工具准备 Node.js安装 安装方法&#xff1a;点击查看WebStorm安装 下载地址&#xff1a;点击查看 二、环境准备 镜像准备 1.查看代理&#xff1a;npm get registry 2.设置淘宝镜像 2.1临时使用. npm --registry https://registry.npm.taobao.org ins…