【Linux】:共享内存

news2024/11/15 21:32:57

共享内存

  • 一.原理
  • 二.创建共享内存
    • 1.shmget
    • 2.写一个共享内存代码
  • 三.进行通信
    • 1.各种接口
    • 2.各接口使用代码
    • 3.一次简单的通信
    • 四.共享内存的特点

一.原理

直接原理

共享内存顾名思义就是共同使用的一块空间。

在这里插入图片描述

很明显操作系统需要对这块内存进行管理,那么就避免不了先描述后组织的策略。

二.创建共享内存

1.shmget

申请一块共享内存-shmget

在这里插入图片描述

第二个参数:创建共享内存的大小,单位字节。

第三个参数:多个选项
在这里插入图片描述

返回值:如果成功返回共享内存标识符,如果失败返回-1。

操作系统怎么保证不同进程看到同一个共享内存呢?怎么知道这块内存是否存在呢? 这就需要对第一个参数进行讨论了。

在这里插入图片描述

2.写一个共享内存代码

comm.hpp

#ifndef __COMM_HPP__
#define __COMM_HPP__
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

using namespace std;

const int size=4096;
const string path="/home/chz";//任意写
const int proj_id=0x6666;//任意写

key_t Getkey()//获取一个key
{
  key_t k=ftok(path.c_str(),proj_id);
  if(k<0)
  {
    perror("Create key wrong\n");
    exit(1);
  }
  cout<<"Create key sucess,key:"<<k<<endl;
  return k;
}

int GetshareMem()//获取一个chmid
{
  key_t k=Getkey();
  int shmid=shmget(k,size,IPC_CREAT|IPC_EXCL|0666);//创建方式和权限
  if(shmid<0)
  {
    perror("Create shmget wrong\n");
    exit(2);
  }
  cout<<"Create shmget sucess,shmid;"<<shmid<<endl;
  return shmid;
}

#endif

前面说过共享内存如果不主动释放会一直存在,所以在调用该函数后我们可以使用ipcs -m查看内核的进程资源。

在这里插入图片描述

perms是权限,nattch是与之相连的文件,byte是共享内存大小(建议一般按4096的整数倍创建,因为系统一次分配的最小内存是4KB)。

使用ipcrm -m+shmid可以手动删除。

在这里插入图片描述

三.进行通信

1.各种接口

将共享内存挂入

在这里插入图片描述

第一个参数毫无疑问是共享内存标识符。

第二个参数一般设置为NULL。因为共享内存是在物理内存上,要将其挂到虚拟内存的共享区,但具体挂到共享区哪个位置一般由操作系统决定。该函数的返回值就是具体的起始地址。

第三个参数一般设为0。它是改变挂接时的权限,虽然我们设置的共享内存权限是666,但可以通过这个参数让它只读。

取消挂入

在这里插入图片描述

控制共享内存

在这里插入图片描述

第二个参数:要进行什么操作。(有许多参数可以自行查看,这里使用 IPC_RMID删除该共享内存)

第三个参数:共享内存的属性。

2.各接口使用代码

processa.cc

#include"comm.hpp"
#include <unistd.h>


int main()
{
  int shmid=GetshareMem();

  sleep(3);
  char*shmaddr=(char*)shmat(shmid,NULL,0);//将共享内存挂入
  cout<<"挂入内存"<<endl;

  sleep(3);
  shdit(shmaddr);//取消挂入
  cout<<"取消挂入"<<endl;

  sleep(3);
  shmctl(shmid,IPC_RMID,nullptr);//销毁共享内存
  cout<<"销毁共享内存"<<endl;



  return 0;
}

在这里插入图片描述

3.一次简单的通信

稍微修改一下comm.hpp,主要在shmget,当一个进程创建时,让另一个进程能获取

#ifndef __COMM_HPP__
#define __COMM_HPP__
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>


using namespace std;

const int size=4096;
const string path="/home/chz";//任意写
const int proj_id=0x6666;//任意写

key_t Getkey()//获取一个key
{
  key_t k=ftok(path.c_str(),proj_id);
  if(k<0)
  {
    perror("Create key wrong\n");
    exit(1);
  }
  cout<<"Create key sucess,key:"<<k<<endl;
  return k;
}

int GetShareMemHelper(int flag)//获取一个chmid
{
  key_t k=Getkey();
  int shmid=shmget(k,size,flag);//创建方式和权限
  if(shmid<0)
  {
    perror("Create shmget wrong\n");
    exit(2);
  }
  cout<<"Create shmget sucess,shmid;"<<shmid<<endl;
  return shmid;
}

int CreateShm()
{
  return GetShareMemHelper(IPC_CREAT|IPC_EXCL|0666);
}

int GetShm()
{
  return GetShareMemHelper(IPC_CREAT);
}

#endif

processa.cc

#include"comm.hpp"
#include <unistd.h>


int main()
{
  int shmid=CreateShm();//创建共享内存
  //挂入内存
  //获取起始地址,并把它当作字符串使用
  char*shmaddr=(char*)shmat(shmid,nullptr,0);
  while(true)
  {
    //直接读取
    cout<<"I am read:";
    cout<<shmaddr<<endl;
    sleep(1);
  }
  shmdt(shmaddr);//取消挂起
  shmctl(shmid,IPC_RMID,nullptr);
  return 0;
}

processb.cc

#include"comm.hpp"

int main()
{
  int shmid=GetShm();//获取共享内存
  //挂入内存
  //获取起始地址,并把它当作字符串使用
  char*shmaddr=(char*)shmat(shmid,nullptr,0);

  while(true)
  {
    cout<<"please Enter:";
    fgets(shmaddr,4096,stdin);//直接从键盘读入
  }

  return 0;
}

makefile

.PHONY:all
all:processa processb

processa:processa.cc
	g++ -o $@ $^ -std=c++11
processb:processb.cc
	g++ -o $@ $^ -std=c++11

.PHONY:clean
clean:
	rm -f processa processb

在这里插入图片描述

四.共享内存的特点

1.共享内存没有同步互斥之类的保护机制。(即使没有写入也依然会读)
2.共享内存是所有的进程通信中最快的。(拷贝少)
3.共享内存里的所有数据由用户自己维护。(操作系统不会自动将数据清零)

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

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

相关文章

C#,数值计算——插值和外推,PolCoef的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// polynomial coefficients from polynomial values /// </summary> public class PolCoef { public PolCoef() { } /// <summary>…

CSDN流量卷领取和使用保姆级教程——流量卷,恭喜获得每日任务奖励【1500曝光】可获得新增曝光,阅读转化,点赞转化,新增关注-流量卷,流量卷,流量卷

希望本文能够给您带来一定的帮助&#xff0c;文章粗浅&#xff0c;敬请批评指正&#xff01; 目录 话不多说&#xff0c;直接上干货&#xff1a; 第一步&#xff1a;流量卷领取教程&#xff1a;点击内容管理&#xff1a;​编辑 第二步&#xff1a;点击首页&#xff1a;​编辑…

上海亚商投顾:北证50指数大涨 机器人概念股掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡反弹&#xff0c;黄白二线有所分化&#xff0c;题材热点轮动表现。北证50指数大涨超3%&#…

深入解析数据结构与算法之堆

文章目录 &#x1f966;引言&#xff1a;&#x1f966;什么是堆&#x1f966;大顶堆与小顶堆&#x1f9c4;大顶堆&#xff08;Max Heap&#xff09;&#x1f9c4;小顶堆&#xff08;Min Heap&#xff09; &#x1f966;堆的表示&#x1f9c4;数组表示&#xff1a;&#x1f9c4;…

智能座舱架构与芯片- (8) 视觉篇

一、概述 相比起用于ADAS感知系统的摄像头&#xff0c;用于智能座舱内部的摄像头&#xff0c;其功能特性和性能要求相对简单。例如&#xff0c;OMS乘客监控摄像头&#xff0c;一般达到5MP即可有良好的效果。同时&#xff0c;OMS也可应用于车内会议系统&#xff0c;还应用于车内…

利用OpenCV实现图片中导线的识别

下面是一个需求&#xff0c;识别图片中的导线&#xff0c;要在图像中检测导线&#xff0c;我们需要采用不同于直线检测的方法。由于OpenCV没有直接的曲线检测函数&#xff0c;如同它对直线提供的HoughLines或HoughLinesP&#xff0c;检测曲线通常需要更多的图像处理步骤和算法&…

多线程的概念

点击链接返回标题-> 什么是进程&#xff1f; 进程&#xff08;Process&#xff09;&#xff0c;是程序的基本执行实体。 在早期面向进程设计的计算机结构中&#xff0c;进程是程序的基本执行实体&#xff1b; 在当代面向线程设计的计算机结构中&#xff0c;进程是线程的容器…

上海亚商投顾:沪指冲高回落 短剧、地产股集体走强

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数早盘冲高&#xff0c;创业板指盘初涨超1%&#xff0c;午后则集体下行翻绿&#xff0c;北证50一度大涨…

MyBatis:关联查询

MyBatis 前言关联查询附懒加载对象为集合时的关联查询 前言 在 MyBatis&#xff1a;配置文件 文章中&#xff0c;最后介绍了可以使用 select 标签的 resultMap 属性实现关联查询&#xff0c;下面简单示例 关联查询 首先&#xff0c;先创建 association_role 和 association_…

win11,引导项管理

1&#xff0c;打开cmd,输入msconfig 2,进入引导选项卡 3&#xff0c;删除不需要的引导项

Go语言常用命令详解(三)

文章目录 前言常用命令go get示例参数说明 go install示例参数说明 go list示例 go mod示例参数说明 go work基本用法示例 go tool示例 go version示例 go vet示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命…

支付宝生僻字选择器

本文的数据来源于支付宝网页版本生僻字选择器。 let rareWords[{spell: "a",words: ["奡", "靉", "叆"]}, {spell: "b",words: ["仌", "昺", "竝", "霦", "犇", "愊…

mysql底层是如何存放数据的

总览 首先总的来说&#xff0c;分为四个层级&#xff0c;行页区段。行就是数据库里的一行数据。 但一次从磁盘读进内存的数据量是一页&#xff08;页是读写的单位&#xff0c;默认16KB一页&#xff09;&#xff0c;页分很多种类&#xff0c;例如数据页、溢出页、undo日志页。 …

Rust语言精讲:数据类型全解析

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将深入探讨Rust语言中的数据类型&#xff0c;这是理解和掌握Rust的基础。 Rust语言数据类型概览 Rust是静态类型语言&#xff0c;所有变量类型在编译时确定。Rust的数据类型分为两类&#xff1a;标量类型和复合类型。…

909-2014-T3

文章目录 1.原题2.算法思想3.关键代码4.完整代码5.运行结果 1.原题 有n个顶点的无向图&#xff0c;使用邻接矩阵作为存储结构。为减少存储空间&#xff0c;使用数组按照行主映射方式仅保存下三角矩阵。请给出映射公式&#xff0c;并编写算法计算给定顶点的度。叙述算法思想并用…

基于ubuntu20.04安装ros系统搭配使用工业相机

基于ubuntu20.04安装ros系统搭配使用工业相机 1. ROS系统安装部署1.1更新镜像源1.1.1 备份源文件1.1.2 更新阿里源1.1.3 更新软件源 1.2 ros系统安装1.2.1 添加ros软件源1.2.2 添加秘钥1.2.3 更新软件源1.2.4 配置及更换最佳软件源1.2.5 ROS安装1.2.6 初始化rosdep1.2.7 设置环…

【Hello Go】Go语言文本文件处理

文本文件处理 字符串处理字符串操作ContainsJoinindexrepeatReplaceSplitTrimFields 字符串转换AppendFormatParse 正则表达式Json处理编码Json通过结构体生产Json通过map生产json 解码Json解析到结构体解析到interface 文件操作相关api介绍建立和打开文件关闭文件写文件读文件…

基于Apache部署虚拟主机网站

文章目录 Apache释义Apache配置关闭防火墙和selinux 更改默认页内容更改默认页存放位置个人用户主页功能基于口令登录网站虚拟主机功能基于ip地址相同ip不同域名相同ip不同端口 学习本章完成目标 1.httpd服务程序的基本部署。 2.个人用户主页功能和口令加密认证方式的实现。 3.…

Linux02 VIM编辑器

Linux02 VIM编辑器 基本上 vi/vim 共分为三种模式&#xff0c; 分别是命令模式&#xff08;Command mode&#xff09;&#xff0c;输入模式&#xff08;Insert mode&#xff09;和底线命令模式&#xff08;Last line mode&#xff09;。 三种状态进行切换 插入模式&#xff1a…

【机器学习】039_合理初始化

一、稳定训练 目标&#xff1a;使梯度值在更合理的范围内 常见方法如下&#xff1a; 将乘法变为加法 ResNet&#xff1a;当层数较多时&#xff0c;会加入一些加法进去 LSTM&#xff1a;如果时序序列较长时&#xff0c;把一些对时序的乘法做加法 归一化 梯度归一化&…