Linux学习之system V

目录

一,system V共享内存

快速认识接口

 shmget(shared memory get)

shmat(shared memory attach)

shmdt(shared memory delete)

 shmctl (shared memory control)

 编写代码

综上那么共享内存与管道通信有什么区别?

system v消息队列

system v信号量


一,system V共享内存

除了管道通信方式,对于操作系统自己本身,操作系统为了内核中的通信单独设计了通信模块。

进程通信的前提:让不同进程看到同一份资源

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到 内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

首先我们从shared memory,共享内存开始,所谓的共享内存,本质上就是将同一份资源,通过加载到物理内存,同时映射到两个进程的内存空间,实现资源共享。

此外,在操作系统中一定会允许多个共享内存,此时就需要操作系统来管理这些共享内存。

快速认识接口

 shmget(shared memory get)

创建共享内存 既能创建,又能获取

参数一为创建的key,参数二为空间大小,

参数三为标记位:

 IPC_CREAT   to create a new segment.  If this flag is not used, then shmget() will find the segment associated with key and check to see . if  the user has permission to access the segment.(没有就创建shm(共享内存))

PC_EXCL    used with IPC_CREAT to ensure failure if the segment already exists.(通常与IPC_CREAT结合使用,不存在就创建,存在就出错返回不创建)。

通过这两个标志位使得我们创建的内存是全新的。

shmat(shared memory attach)

将共享内存挂接到地址空间当中

参数一位shmid,参数2一般设置位nullptr,参数三为标志位表示已什么样的方式挂在,一般也用0。

返回值位起始地址。通过引用计数来计算有多少进程挂在到当前共享内存中。

shmdt(shared memory delete)

去掉内存关联,将共享内存从进程地址空间中移除。

 shmctl (shared memory control)

控制共享内存,第一个参数位shmid,第二个位操作指令,IPC_STAT,IPC_SET, IPC_RMID(删除) ,IPC_INFO

 编写代码

和命名管道通信的方式一样,我们创建了三个文件server,client,commant.cpp,用来观察进程通信:

首先对于读端还是写端都会有同一个key,我们创建同一个key,此时进程就会把key写到地址空间当中,通过Key值操作系统可以找到两个进程的同一块地址空间,即key值指向的内存就是共享内存。

comman.hpp

#pragma once
#include<iostream>
#include<string>
#include<cstdlib>
#include<unistd.h>
const std::string pathname="/home/danchengwei/myfile/file7";
const int proj_id=0x11223344;
const int size=4096;
//管道文件
const std::string filename = "fifo";key_t getkey(){//转换pathname为keykey_t key=ftok(pathname.c_str(),proj_id);//convert a pathname and a project identifier to a System V IPC keyif(key<0){std::cerr<<"errno:"<<errno<<",strerror"<<strerror(errno)<<std::endl;return 1;}std::cout<<"key:"<<key<<std::endl;return key;}std::string tohex(int id){char buffer[1024];snprintf(buffer,sizeof(buffer),"0x%x",id);return buffer;}int creatshmHLPER(key_t key,int flag){int shmid=shmget(key,size,flag); //成光返回id,错误返回-1if(shmid<0){std::cerr<<"errno:"<<errno<<",strerror"<<strerror(errno)<<std::endl;exit(2);}std::cout<<"shmid:"<<shmid<<std::endl;return shmid;}int getshm(key_t key){return creatshmHLPER(key,IPC_CREAT | IPC_EXCL | 0644);}int creatshm(key_t key){return creatshmHLPER(key,IPC_CREAT);}bool MakeFifo()
{int n = mkfifo(filename.c_str(), 0666);if(n < 0){std::cerr << "errno: " << errno << ", errstring: " << strerror(errno) << std::endl;return false;}std::cout << "mkfifo success... read" << std::endl;return true;
}

server

#include<iostream>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include"comman.hpp"
using namespace std;int main()
{//创建共享内存key_t key=getkey();//key在应用层我们一般不去使用,我们使用的是shmid int shmid=creatshm(key);sleep(10);//挂载 ,即将共享内存映射到进程的地址空间当中。char*s=(char*)shmat(shmid,nullptr,0);//打开管道Start:int rfd=open(filename.c_str(),O_RDONLY);if(rfd<0){//cerr<<"errno:"<<errno<<",errstring:"<<strerror(errno)<<endl;if(MakeFifo()){goto Start;}else{return 1 ;}//return 2;}cout<<"打开管道成功..."<<endl;char buffer[1024];while(true){ssize_t s=read(rfd,buffer,sizeof(buffer)-1);if(s>0){buffer[s]=0;//表示以/0结尾cout<<"cilent reply: "<<buffer<<endl;}if(s<=0){cout<<"no data had reciveed"<<endl;//没有数据可读了,退出进程break;}}//关闭管道close(rfd);cout<<"关闭管道成功..."<<endl;sleep(5);//在地址空间当中移除共享内存shmdt(s); sleep(5);//按照id删除shmctl(shmid,IPC_RMID,nullptr);sleep(5);return 0;}

创建完成可以通过指令查看共享内存:

ipcs -m  //查看共享内存
ipcrm -m shmid  //删除共享内存

其中natch表示有几个进程挂接到该共享内存。

程序结束,共享内存被创建之后并没有释放。它的生命周期时内核决定的。

之后我们再完成与server一样的client的编写:

#include<iostream>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include"comman.hpp"
using namespace std;int main()
{//与server一样//获取key值key_t key=getkey();//创建共享内存int shmid=creatshm(key);sleep(10);//把共享内存挂载到地址空间当中char *s=(char*)shmat(shmid,nullptr,0);sleep(5);//打开管道int wfd = open(filename.c_str(), O_WRONLY);//数据写入string message;while(true){cout<<"请输入你要发送的数据:"<<endl;getline(cin,message);//这里再写入管道时,我们使用c++string再转化为c字符串ssize_t t=write(wfd,message.c_str(),message.size());if(t<0){cerr<<"错误码:"<<errno<<",错误原因:"<<strerror(errno)<<endl;break;}}//关闭管道close(wfd);cout<<"关闭管道成功..."<<endl;//取消共享内存的挂载shmdt(s);return 0;
}

之后我们就可以同时执行两个进程并观察会发现 ,刚开始创建共享内存,server与client挂载到地址空间,natch增加,之后移除,之后删除.

有了共享内存,那么我们现在通过共享内存就可以实现进程之间的通信,和管道类似,我们可以增加一个管道文件;之后用一端作为读端,一端作为写端。

综上那么共享内存与管道通信有什么区别?

其实共享内存是比管道通信更加快速的,对于共享内存,考虑硬件:

第一次拷贝是从外设到共享内存,第二次是从共享内存写到显示器上,只需要拷贝两次,对于管道.

而对于管道,先是用户到键盘(外设)把数据读到缓冲区中,再把数据拷贝到管道当中(写入),之后再将管道的数据写道别的用户的缓冲区(读),最后再将数据给到显示器(外设)。对于管道考虑硬件需要拷贝四次数据。

system v消息队列

所谓的消息队列是提供让一个进程给另一个进程发送数据块的能力,使用的接口msgctl,使用方法基本和共享内存大致相同。

参数一为msqid即这里的key,参数二为如何去操作消息队列的指令,参数三一般为nullptr.

创建完成之后可以用指令ipcs -q来查看消息对列。根据接口的第二参数我们可以还选择删除消息队列。可以看到使用与共享内存非常的相似。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<iostream>
#include"comman.hpp"//消息队列
int main()
{//获取key值key_t key=getkey();//创建消息队列int msgid=msgget(key,IPC_CREAT | IPC_EXCL);std::cout<<"msgid:"<<msgid<<std::endl;sleep(10);//删除消息队列msgctl(msgid,IPC_RMID,nullptr);rteurn 0;
}

其次消息队列也可以存在多个,两个进程用多个消息队列进行数据交互,因此在内核当中,操作系统需要管理这些消息队列,先描述在组织,因此消息队列的管理就是消息队列加自身的属性。

关于消息队列大家感兴趣可以查看手册的使用。

system v信号量

信号量主要用于同步和互斥的,当进程们面对同一份资源时,我们的资源就需要被保护起来,而信号量就是为了保护我们的共享资源。

因此我么先来了解同步与互斥:

进程互斥
程互斥则是一种防止多个进程同时访问同一资源的机制。在进程互斥的机制下,当一个进程正在访问某个共享资源时,其他进程需要等待该进程释放该资源之后才能访问。实现进程互斥的主要方法有互斥锁和信号量。

进程同步

指的是多个进程在共享资源的过程中保持一致性的机制。其主要目的是避免进程间的竞争和冲突,确保多个进程对共享资源的访问按照一定的顺序和规则进行,从而避免资源的竞争和冲突。

进程同步的实现方法包括信号量、互斥锁、条件变量等。
 

对于linux系统就是用洗脑两盒互斥锁来解决同步与互斥的问题。

信号量(semaphore),我们在linux中也有对应的函数接口:

semget 获取创建信号量

semctl 控制信号量

数1为semid,参数二为编号(起始从0开始),参数三为指令。

semop 操作信号量

对信号量做加加减减操作

 

可以看到无论是共享内存,还是消息对列或者信号量,他们都是有统一的标准的接口,因此这里的函数我们也能使用了。

返回值一般我们叫做semid,参数一为key值,参数二为创建的个数,参数三为标志.

利用指令ipcs -s 可以查看创建的信号量,可以看到创建完进程结束,但信号量还在,因此生命周期还是随内核。

当然对于信号量,也是需要被操作系统管理,管理信号量及其信号量属性。

其次内核是怎样看待IPC资源(共享资源):

首先肯定有两部分:1.会有单独设计的一个模块。2.会有特定的保护机制。

所谓的信号量本身就是一个计数器,为了让进程通信,多个执行流共享同一份资源,而公共资源被并发访问就会产生数据不一致的问题,因此我们就需要保护我们的共享资源来面对同步与互斥的两个情况。

解决同步与互斥简单来说就是,互斥:任何一个时刻只允许一个执行流来使用该资源。同步:多个执行流都来使用该资源时,让他按照一定的顺序来执行。

信号量通俗点说,就是资源数目的计数器,每一个执行流想要访问资源内的某一份资源,不应该执行流直接访问,而是先申请信号量资源,(其实就是对计数器信号量--操作),申请成功后,就完成了对资源的预定机制,如果申请不成功,则执行流就进行阻塞。

我们在编写代码时如果想要访问这一份共享资源,先要申请信号量资源,如果成功,则返回之后的信号量,失败就阻塞。而阻塞的这一部分资源就是临界资源。

但也有特殊情况,只有一个信号量即只允许一个人访问的资源,这种信号量被叫做二元信号量,即就是一个锁的功能---互斥锁。

原子性:只有两种状态,要么不做,要么做完。

本次我们主要先 认识一下。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

08 MyBatis之查询专题(返回对象/Map/List封装Map/Map封装Map)+列名与属性名映射的三种方法

准备: INSERT INTO t_car (id, car_num, brand, guide_price, produce_time, car_type) VALUES (165, 6666, 丰田霸道, 32.00, 2020-11-11, 燃油车); INSERT INTO t_car (id, car_num, brand, guide_price, produce_time, car_type) VALUES (166, 1202, 大众速腾, 30.00, 2020…

搜维尔科技:AR/VR技术对制造业劳动力危机的影响

借助 AR/VR 的力量缩小现代制造业的技能差距 数字化转型仍然是企业的首要任务&#xff0c;其许多方面都需要人工干预。然而&#xff0c;推动此类举措所需的技术工人日益短缺。这就造成了我们所说的“制造业劳动力危机”。 了解以下详情&#xff1a; 制造业用工危机正在影响产…

算法沉淀——动态规划之回文串问题(上)(leetcode真题剖析)

算法沉淀——动态规划之回文串问题 01.回文子串02.最长回文子串03.分割回文串 IV04.分割回文串 II05.最长回文子序列06.让字符串成为回文串的最少插入次数 01.回文子串 题目链接&#xff1a;https://leetcode.cn/problems/palindromic-substrings/ 给你一个字符串 s &#xf…

Android 架构MVI、MVVM、MVC、MVP

目录 一、MVC&#xff08;Model-View-Controller&#xff09; 二、 MVP&#xff08;Model-View-Presenter&#xff09; 三. MVVM&#xff08;Model-View-ViewModel&#xff09; 四. MVI&#xff08;Model-View-Intent&#xff09; 五.MVI简单实现 先简单了解一下MVC、MVP和…

LabVIEW磁阻自动优化测量系统

LabVIEW磁阻自动优化测量系统 介绍了一种基于LabVIEW开发的磁阻自动优化测量系统&#xff0c;通过自动优化测试分辨率和高度模块化设计&#xff0c;大幅提升磁阻测试的效率和准确性。系统采用功率电源、电磁铁、高分辨率特斯拉计、步进电机转动器、精密电流源与精准电压表等硬…

ruoyi框架学习

RBAC模型 数据字典 拦截器 token没有&#xff0c;submit&#xff0c;request.js中&#xff0c;前端前置拦截器&#xff0c;响应拦截器 后台 注解

Word | 论文使用 Springer LNICST 工具包进行格式化

目录 Step1&#xff1a;下载 Springer LNICST 工具包 Step2&#xff1a;导入宏文件 Step3&#xff1a;处理导入失败&#xff08;大概意思是这个宏不安全&#xff09; Step4&#xff1a;导入成功并使用 Step1&#xff1a;下载 Springer LNICST 工具包 会议官网的 SUBMISSIO…

当你使用ChatGPT时,选择合适的提示(prompt)是引导对话方向的关键

马斯克曾说&#xff0c;人生中最重要的事情&#xff0c;就是提出真正的好问题。 因此&#xff0c;我要开始接触某个新领域&#xff0c;并且开始要自主学习的时候&#xff0c;我首先要问自己这个问题&#xff1a; 我为什么要学这个&#xff0c;学这个的目的是为了创造什么&#…

project.config.json 文件内容错误] project.config.json: libVersion 字段需为 string, string

家人们&#xff0c;遇到了一个新的报错 于是从网上找了各种方法&#xff0c;有说把开发者工具关闭重启的&#xff0c;有说开发者工具下载重新下载的&#xff0c;有说开发者工具路径安装得在C盘的&#xff0c;均没有效果 解决方法&#xff1a; 1、运行项目&#xff0c;在开发者…

软件需求分析报告(直接套用)

技术要求 1.1接口要求 1.2可靠性&#xff0c;稳定性&#xff0c;安全性&#xff0c;先进性&#xff0c;拓展性&#xff0c;性能&#xff0c;响应。 2.系统安全需求 2.1物理设计安全 2.2系统安全设计 2.3网络安全设计 2.4应用安全设计 2.5用户安全管理 全套资料过去进主页。

Vue3之属性传值的四种情况

文章目录 Vue3之属性传值的四种情况一、引言二、父组件向子组件传值三、子组件向父组件传值四、祖先组件向后代组件传值五、兄弟组件之间传值 Vue3之属性传值的四种情况 一、引言 在vue3中&#xff0c;组件与组件之间是可以传递属性的&#xff0c;包括三种类型&#xff1a; …

爱旅行平台的设计与实现

爱旅行平台的设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全

Oracle中序列

1. Sequence 定义 在Oracle中可以用SEQUENCE生成自增字段。Sequence序列是Oracle中用于生成数字序列的对象&#xff0c;可以创建一个唯一的数字作为主键。 2. 为什么要用 Sequence 你可能有疑问为什么要使用序列&#xff1f; 不能使用一个存储主键的表并每次递增吗&#xf…

java 反射机制 (一)

java反射机制&#xff1a; 即通过外部文件配置&#xff0c;不修改文件源码的情况下&#xff0c;来控制程序&#xff0c;也符合设计模式的OCP原则&#xff08;开闭原则&#xff1a;不修改源码&#xff0c;扩容原则&#xff09; Java Reflection 1.反射机制允许程序在执行期间…

Spring中的事务和事务的传播机制

事务是一组操作的集合&#xff0c;不可以被分割。事务会把所有的操作作为一个整体&#xff0c;这组操作要么全部成功&#xff0c;要么全部失败。 事务有三种操作&#xff1a; 开启事务&#xff1b;提交事务&#xff1b;回滚事务。 如果代码的执行逻辑是这样&#xff1a; 开…

dolphinscheduler海豚调度(三)SQL任务

在之前的博文中&#xff0c;我们已经介绍了DolphinScheduler海豚调度的基本概念和模块&#xff0c;安装部署和元数据切换&#xff0c;以及Shell任务的实践。今天&#xff0c;让我们来深入探讨DolphinScheduler中另一种常见的任务类型&#xff1a;SQL任务。 SQL任务是DolphinSc…

弹窗内容由后端返回,如何让点击按钮的事件交由前端控制?

一、场景 背景&#xff1a;因为系统里经常有新活动或者公告需要通知所有用户&#xff0c;希望前端维护的这个弹窗里的内容可以由后端接口返回。这样就不需要每次上新活动的时候&#xff0c;前端项目都发版了。因此&#xff0c;前端维护了这个弹窗和它的关闭事件&#xff0c;至…

人工智能之Tensorflow常用API

TensorFlow的计算表现为数据流图&#xff0c;所以tf.Graph类中包含一系列表示计算的操作对象(tf.Operation)&#xff0c;以及在操作之间流动的数据–张量对象(tf.Tensor)。 Graph tf.Graph类包含图相关的API操作&#xff0c;可以在jupyter notebook导入tensorflow之后执行hel…

前端Vue项目无法启动服务,提示无 ‘dev‘ npm的脚本问题解决

目录 一、问题详情 二、问题解决 一、问题详情 上周还能运行的项目&#xff0c;今天突然无法执行了&#xff0c;连最基本的启动按钮也没有了&#xff0c;所有的项目本地都突然跑不起来了&#xff0c;附上截图。 二、问题解决 后来排查的根本原因有点奇葩&#xff0c;是因为…

【踏雪无痕的痕四】——0到底是有还是没有?

目录 一、背景介绍三、过程1.0的历史发展&#xff1f;2.如何将0讲给一个刚上一年级的孩子&#xff1f;3.0的边界和意义&#xff1f;4.那四年&#xff0c;到底在培养什么&#xff1f;和0有什么关系&#xff1f; 四、总结 一、背景介绍 最近在看一年级数学&#xff0c;其中介绍到…