Linux--进程间通信(2)--共享内存--1126

news2024/11/27 0:28:04

1.共享内存的原理

进程A先申请一段内存空间,其页表映射到物理空间,进程B通过A的页表映射,将B的页表也同样映射到同一块物理空间。

释放共享内存

各自修改各自的页表指向并释放共享内存

2.共享内存的建立过程

头文件 comm.hpp

#pragma once

#include <iostream>
#include <cstdio>
#include <ostream> //注意这个
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cassert>
#include <unistd.h> //sleep()
#include "myLog.hpp"

using namespace std;

#define PATH_NAME "/home/chy"  //这个路径随便 但要保证自己有权限去访问
#define PROJ_ID 0x66 //任意
#define SHM_SIZE 4096 //最好是页(4096)的整数倍

2.1 ftok 

通过一定的算法形成唯一值给需要通信的两个进程使用

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char* pathname,int proj_id)

pathname :给一个路径值

proj_id:随便给

ftok会将路径值得inode编号和proj_id值进行一定运算形成一个唯一值

#include "comm.hpp"
int main()
{
    //1.创建共享内存
    key_t k=ftok(PATH_NAME,PROJ_ID);//形成key
    Log("创建key成功",Debug)<<"server key:"<<k<<std::endl;
    return 0;
}

 

创建失败返回-1

2.2 shmget

#include <sys/ipc.h>   #include <sys/shm.h>

int shmget(key_t key,size_t size,int shmflg);
key  :一个随机数通过 ftok去创建 目的是让两个进程有一个相同的编号,以看到同一块共享内存。
size : 要申请多大的共享内存,最好是4096的整数倍
shmflg: 可以是 IPC_CREAT  创建共享内存,如果底层已经存在就获取它,如果不存在就创建它,并返回。
也可以是 IPC_CREAT | IPC_EXCL 底层不存在就创建,如果底层存在就出错返回。

返回值:共享内存的用户层标识符,类似fd

创建失败返回-1

 int main()
{
    //2.创建共享内存-- 建议创建一个全新的共享内存
    int shmid=shmget(k,SHM_SIZE,IPC_CREAT| IPC_EXCL |0666);//带上权限
    if(shmid==-1)
    {
        perror("shmget");
        exit(1);
    } 
//...
}


 当进程运行结束时,我们的共享内存依然存在。

2.3 ipc资源的删除

system V IPC 资源,生命周期随内核只能通过手动删除或代码删除。

1.手动删除

bash: ipcs -m

查看共享内存

bash:ipcrm -m shmid

删除共享内存


2.代码删除

 shmctl

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds * buf);

cmd有:IPC_STAT  获取共享内存的属性  IPC_SET设置共享内存的相关属性

                IPC_RMID 标记共享内存被删除

buf :是一个数据结构的指针 删除时设为空就行


  //删除共享内存
 int n=shmctl(shmid,IPC_RMID,nullptr);
 assert(n!=-1);
 (void)n;
 Log("删除共享内存成功",Debug)<<"shmid: "<<shmid<<endl;

 

 失败返回-1


2.4 shmat

关联挂接

#include <sys/tpes.h>
#incldue <sys/shm.h>

void* shmat(int shmid ,const void* shmaddr,int shmflg);

shmaddr 挂接到的虚拟地址位置(不推荐给参数)设为nulltpr 即可

shmflg 可以以只读等方式进行挂接 设为0即可

//3.将指定的共享内存挂接到自己的地址空间
    char* shmaddr=(char*)shmat(shmid,nullptr,0);
    Log("链接成功",Debug)<<"shmid: "<<shmid<<endl;

 返回值是虚拟地址,失败返回-1


2.5 shmdt

去关联

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void* shmaddr);

shmaddr 就是shmat的返回值

 

 失败返回-1

3 运行结果

./shmserver

 4 客户端

#include "comm.hpp"
int main()
{
    //1.获取k
    key_t k=ftok(PATH_NAME,PROJ_ID);//形成key
    if(k<0)
    {
        Log("创建key失败",Error)<<"client key: "<<k<<endl;
        exit(1);
    }
    Log("创建key成功",Debug)<<"client key: "<<k<<endl;
    //2.创建共享内存
    int shmid=shmget(k,SHM_SIZE,0);//0即可 IPC_CREAT也行
    if(shmid==-1)
    {
        Log("创建共享内存失败",Error)<<"shmid: "<<shmid<<endl;
        exit(2);
    }
    Log("创建共享内存成功",Debug)<<"shmid: "<<shmid<<endl;
    //3.链接起来
    char* shmaddr=(char*)shmat(shmid,nullptr,0);
    if(shmaddr==nullptr)
    {
        Log("链接失败",Error)<<"shmid: "<<shmid<<endl;
    }
    Log("链接成功",Debug)<<"shmid: "<<shmid<<endl;
    //4.正常使用

    //5.去关联
    int n=shmdt(shmaddr);
    assert(n!=-1);
    Log("去关联成功",Debug)<<"shmid: "<<shmid<<endl;

    //client不需要删除共享内存
    
    return 0;
}

 ./shmclient

5、通信过程

shmat的返回值是虚拟地址,我们可以将它当成一个大字符串。

shmclient.cc

shmclient.cc

结论:

  • 只要是通信双方使用shm,一方直接向共享内存中写入数据,另一方就可以马上看到。共享内存是所有进程间通信(IPC),速度最快的。不需要过多的数据拷贝。
  • 共享内存缺乏访问控制。不管写端在不在,读端都在读,不管读端在不在,写端都在写。不会因为一个进程不存在而阻塞。会带来并发问题。可以通过管道来优化该问题。

 

 

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

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

相关文章

Windows系统dos命令之cmd

目录1. 使用cd命令快速切换到指定的盘符中1.1 参数说明1.2 cd 切换盘符2. 使用cd命令切换到指定的目录中2.1 切换指定目录3. 使用cd命令退回到上一层目录3.1 使用命令 ”cd ..“4. 使用cd命令直接退回到当前根目录下4.1 使用命令cd \1. 使用cd命令快速切换到指定的盘符中 cd 是…

JUC并发编程第十一篇,Java对象的内存布局

JUC并发编程第十一篇&#xff0c;Java对象的内存布局一、对象在堆内存中的存储布局1、对象头对象标记Mark Word类元信息&#xff08;类型指针&#xff09;2、实例数据3、对齐填充二、对象标记&#xff08;MarkWord&#xff09;布局与验证代码验证&#xff08;JOL&#xff09;一…

重点| 系统集成项目管理工程师考前50个知识点(4)

本文章总结了系统集成项目管理工程师考试背记50个知识点&#xff01;&#xff01;&#xff01; 帮助大家更好的复习&#xff0c;希望能对大家有所帮助 比较长&#xff0c;放了部分&#xff0c;需要可私信&#xff01;&#xff01; 26、编制范围管理计划的输出&#xff1a; 范…

Flink Window Function

窗口函数定义了要对窗口中收集的数据做的计算操作&#xff0c;根据处理的方式可以分为两类&#xff1a;增量聚合函数和全窗口函数。 文章目录1.增量聚合函数1.1 ReduceFunction1.2 AggregateFunction2.全窗口函数2.1 WindowFunction2.2 ProcessWindowFunction3.增量聚合和全窗口…

【MySQL】用户管理

文章目录用户管理用户信息创建用户删除用户修改用户密码用户权限用户赋权回收权限用户管理 如果我们只能使用root用户,这样存在安全隐患,因为root可以访问所有的数据库和表,这时,就需要使用MySQL的用户管理,从而限制某个特定的用户只能访问特定的数据库和表,并且对其权限作出一…

【51-订单模块-资源整合-整合SpringSession-订单中心核心逻辑-认证拦截-订单提交-订单生成逻辑-接口幂等性处理-接口幂等性解决方案】

一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了&#xff0c;请点击这里&#xff01;】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…

若依上面添加layui组件

1.因为若依本身有layui&#xff0c;所以不需要在引layui的css与js 2.下面是需要添加的 <div className"layui-btn-container" style"margin-top: 30px;"><button data-method"setTop" οnclick"sjhdekjshd()">多窗口模式…

基于vite搭建的vue3项目中如何引用环境变量

目录 回顾一下vue-cli2/cli3中环境变量使用方法 环境变量定义&#xff1a; 环境变量使用&#xff1a; vite中环境变量使用方法 环境变量定义&#xff1a; 环境变量使用&#xff1a; 回顾一下vue-cli2/cli3中环境变量使用方法 在vue-cli2/cli3中使用环境变量时 环境变量定…

Python Flask 路由配置

有关更多的Python 开发内容,可访问:《 Python Flask开发指南》 Flask中通过使用route装饰器实现路由访问功能,其路由匹配URL规则基于Werkzeug的路由模块。该模块基于Apache及更早的HTTP服务器主张,希望保证优雅且唯一的URL。其使用格式如下: from flask import Flask app …

突然 Java 倒下了......

TIOBE 公布了 2022 年 12 月的编程语言排行榜。 Java 首次跌出前 3 名。除此之外&#xff0c;Kotlin 和 Julia 也越来越接近 Top 20。 TIOBE 将于下个月揭晓其 2022 年度编程语言&#xff0c;目前共有 3 个候选者&#xff1a;Python、C 和 C。TIOBE CEO Paul Jansen指出&#…

如何实现工具无关化?——关于自动化测试脚本的设计

问题的提出 最近几年来&#xff0c;我的自动化测试工具之旅大致是这样的&#xff0c;最早用的是QTP&#xff0c;然后是RFT&#xff08;IBM的功能测试自动化产品&#xff09;&#xff0c;之后也经历了Selenium&#xff0c;Watir等。再后来还是一些商业工具&#xff0c;主要是偏…

KubeClipper 1.3.1 正式发布

2022 年 12 月 12 日&#xff0c;KubeClipper 1.3.1 版本正式发布&#xff01; 开源大事记 2022 年 08 月&#xff0c; KubeClipper 项目正式开源到 https://github.com/KubeClipper 项目。 2022 年 08 月&#xff0c;在由 OpenInfra 基金会举办的 2022 OpenInfra Days China…

nacos--基础--4.1--集成--SpringBoot--配置管理、服务发现、服务注册

nacos–基础–4.1–集成–SpringBoot–配置管理、服务发现、服务注册 代码位置 https://gitee.com/DanShenGuiZu/learnDemo/tree/master/nacos-learn/nacos-spring-boot1、介绍 主要面向 SpringBoot 的使用者通过2个实例&#xff0c;来介绍nacos和SpringBoot的集成 配置管理服…

【案例教程】Python气象海洋数据可视化到常见数据分析方法(折线图、柱状图、errorbar图、流场矢量、散点图、风玫瑰图、流场矢量、填色及等值线+地图)

【查看原文】Python在气象与海洋中的实践技术应用 Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;能够在不同操作系统和平台使用&#xff0c;简洁的语法和解释性语言使其成为理想的脚本语言。除了标准库&#xff0c;还有丰富的第三方库&#xf…

点线面数据处理(wkt,geojson互转)

点线面数据点&#xff1a;[103.8810, 31.0896] 线&#xff1a;[[103.7767, 30.8424],[104.2546, 30.8150],[104.3068, 30.4552]] 面&#xff1a;[[[103.8810, 31.0896],[104.0129, 30.8891],[103.7520, 30.8809],[103.8810, 31.0896]]] wkt数据点&#xff1a;POINT(103.365926 …

对Dueling DQN理论的深度分析。

强化学习中Agent与环境的交互过程是由马尔可夫决策过程(Markov Decision Process, MDP)描述的。MDP对环境做了一个假设&#xff0c;称作马尔可夫性质&#xff0c;即下一时刻的状态只由上一时刻的状态和动作决定。 马尔可夫性质决定了值函数(状态值与动作值函数)可以写成递归的形…

【项目总结】医疗化验单的OCR识别

项目总结 医疗化验单OCR 文章目录项目总结前言一、项目要求二、解决思路1.模型1.扶正2.裁剪3.pipeline三、总结前言 课题组项目的总结。 一、项目要求 课题组和广州的一家药企有合作&#xff0c;甲方要求把一张医疗化验单内的表格内容整体识别出来&#xff0c;特别是化验的数…

测开- Junit 单元测试框架

文章目录前言了解 Junit准备工作 - 在 pom.xml 文件中引入 Junit 相关依赖1、Junit注解TestBeforeEach、BeforeAllAfterEach && AfterAll2、断言1、Assertions - assertEquals 方法2、Assertions - assertNotEquals 方法3、Assertions - assertTrue && assertF…

一个关于React数据不可变的无聊问题

对于一个React的开发者来说不知道你有没有想过为什么React追求数据不可变这个范式&#xff1b; 一个月前我想过一个问题如果我在使用useState这个hooks的时候传入的是一个改变后的引用类型对象会发生什么&#xff1f; 例如&#xff1a; import {useState} from "react&…

css之@media网页适配

原因&#xff1a; 原本是想用 iview Grid 栅格,但以下响应并不符合我的需求 【我需要的分辨率是1920和1536】&#xff0c;所以需要手动修改 解决方案&#xff1a; html <Row> <i-col :xs"6" :sm"6" :md"6" :lg"8"><d…