【LInux】进程间通信(共享内存)

news2024/11/25 19:11:27

文章目录

  • system V共享内存
      • shmget(创建共享内存)
      • ftok(key)
      • ipcs指令
      • shmctl(销毁共享内存)
      • shmat
      • 代码
  • 共享内存

system V共享内存

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据
在这里插入图片描述
共享内存是允许有多个shm存在的,而shm并不是简单的在内存上获取一块空间就结束了,他也是需要管理的因为有多块shm,共享内存=共享内存的属性(struct)+空间

shmget(创建共享内存)

在这里插入图片描述

先来介绍shmget的第二个参数是决定开辟共享内存空间的,
第三个参数当输入IPC_CREAT时,就是如果没有共享内存就创建共享内存,要是有的话就获取已经存在的共享内存并返回
IPC_EXCL是不能单独使用的,要通过和IPC_CREAT联合使用
IPC_CREAT | IPC_EXCL它的意思是如果没有共享内存就创建共享内存,要是有的话就出错返回,它要是成功的话就创建新的共享内存。
而它的第一个参数是由ftok决定的,ftok的返回值就是shmget的第一个参数,下面介绍一下ftok

ftok(key)

在这里插入图片描述

两个完全不相关的进程是通过ftok的值实现共用同一个文件的,ftok的两个参数是两个进程之间约定好的值(自己定义保证双方是相同的),并且得到唯一的ftok值,一个进程创建ftok值,并将它放到要使用的共享内存(struct shm)当中,之后另一进程是通过该值去找这个共享内存,也就实现了共享内存。

ipcs指令

ipcs 命令用于查看 Linux 进程间通信设施的状态,包括消息列表、共享内存和信号量的信息。

ipcs -m   //只用于查看共享内存
ipcrm -m

在这里插入图片描述

共享内存在使用结束后会自己销毁吗?
并不会,当我们下次在创建新的共享内存(ftok相同)时候会发现是失败的(报错),所以也就证明了并不会销毁。所以需要人为的去销毁。ipcrm -m shmid。共享内存的生命周期并不跟随进程,而是跟随系统。

shmctl(销毁共享内存)

经上述问题使用shmctl进行销毁共享内存,它并不止之后销毁的功能还能查看1共享内存的属性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

shmat

在这里插入图片描述

创建完共享内存之后是需要进行链接就可以进行通信了。
它的返回值也就是共享内存开辟的首地址,然后映射到虚拟地址上。

代码

//comm.hpp
#ifndef _COMM_HPP_
#define _COMM_HPP_

#include<iostream>
#include<string>
#include<unistd.h>
#include<cerrno>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#include<cassert>
#include<sys/types.h>
#include<sys/stat.h>

using namespace std;

#define PATHNAME "."
#define PROJID 0x6666
#define gsize 4096

key_t GetKey()
{
    key_t k=ftok(PATHNAME,PROJID);
    if(k==-1)
    {
        cerr<<"errno:"<<errno<<strerror(errno)<<endl;
        exit(-1);
    }
    return k;
}

string ToHex(int a)
{
    char buffer[24];
    snprintf(buffer,sizeof(buffer),"0x%x",a);
    return buffer;
}

static int CreateShmHelp(int k,int size,int flag)
{
    int shmid=shmget(k,size,flag);
    if(shmid==-1)
    {
        cerr<<"errno:"<<errno<<strerror(errno)<<endl;
        exit(-1);
    }
    return shmid;
}

int CreateShm(int k,int size)
{
    umask(0);
    return CreateShmHelp(k,size,IPC_CREAT | IPC_EXCL | 0666);//获取一个新的共享内存
}

int GetShm(int k,int size)
{
    return CreateShmHelp(k,size,IPC_CREAT);
}

//链接共享内存
char* attachShm(int shmid)
{
    char *start = (char*)shmat(shmid, nullptr, 0);
    return start;
}
//断开链接共享内存
void detachShm(char *start)
{
    int n = shmdt(start);
    assert(n != -1);
    (void)n;
}

void DelShm(int shmid)//删除是需要权限的,但是我们以上面的方法创建的权限都是0
{                     //所以要想顺利删除使用sudo,或者在创建那里设置权限,也就是现在的样子
    int n=shmctl(shmid,IPC_RMID,nullptr);
    assert(n!=-1);
    (void)n;
}

#endif
//server.cc
#include"comm.hpp"

int main()
{
    key_t k=GetKey();
    cout<<"serverK:"<<ToHex(k)<<endl;

    int shmid=CreateShm(k,gsize);
    cout<<"serverS:"<<ToHex(shmid)<<endl;

    sleep(5);

    // struct shmid_ds ds;
    // int n=shmctl(shmid,IPC_STAT,&ds);

    // cout<<"perm:"<<ds.shm_perm.__key<<endl;
    // cout<<"pid:"<<ds.shm_cpid<<endl;
    //链接共享内存
    char* start = attachShm(shmid);
    //这里获取的start也就是共享内存开辟的首地址,然后映射到虚拟地址上

    //sleep(10);
    int n = 0;
    while(n <= 30)
    {
        cout <<"client -> server# "<< start << endl;
        sleep(1);
        n++;
    }   
    //断开连接
    detachShm(start);

    DelShm(shmid);
}
//client.cc
#include"comm.hpp"

int main()
{
    key_t k=GetKey();
    cout<<"clientK:"<<ToHex(k)<<endl;

    int shmid=GetShm(k,gsize);
    cout<<"clientS:"<<ToHex(shmid)<<endl;

    char* start = attachShm(shmid);
    int i = 0;
    while (i < 26)
    {
        start[i] = 'A' + i;
        i++;
        start[i] = 0;
        sleep(1);
    }

    //sleep(10);
    //断开连接
    detachShm(start);
}
//makefile
.PHONY:all
all:server client
server:server.cc
	g++ -o $@ $^ -std=c++11
client:client.cc
	g++ -o $@ $^ -std=c++11
	
.PHONY:clean
clean:
	rm -r server client
	

共享内存

共享内存是以page页来存储的单位是4KB,但是当我们需要4097个字节为什么,他就给了4097呢,原因是你需要多少它给多少,但是底层还是已经开辟了8KB

在通信的时候,没有使用任何接口?
一旦共享内存映射到进程的地址空间,该共享内存就直接被所有的进程直接看到了。
因为共享内存的这种特性,可以让进程通信的时候,减少拷贝次数,所以共享内存是所有进程通信速度最快的。
共享内存没有任何的保护机制(同步互斥)?管道是通过系统接口进行通信的(read,write内就有保护机制,确保有没有数据等),而共享内存是直接通信
在这里插入图片描述

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

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

相关文章

新能源突围,需要发力被忽视的中端品牌战场

作者 |张祥威 编辑 |德新 今年2月&#xff0c;受特斯拉等竞品降价影响&#xff0c;深蓝SL03销量下滑至4000台。深蓝的市场部上报长安中国&#xff0c;十天后开始降价&#xff0c;3月SL03销量重回正轨。 在巨头和新势力之间灵活腾挪&#xff0c;深蓝向外界展示了爆款制造的素质…

网络安全知识点梳理(期末不挂科)

网络安全复习知识点太多梳理不清晰&#xff1f;&#x1f44f;&#x1f3fb;&#x1f44f;&#x1f3fb;&#x1f44f;&#x1f3fb; 本文一篇帮你梳理清晰&#xff0c;内容覆盖整个大学网络安全知识点&#x1f44c;&#x1f3fb; 干货满满不看后悔&#x1f44d;&#x1f44…

leetcode 309.最佳买卖股票时机含冷冻期

题目描述 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 卖出股票后&#xff0c;你无法在第二天买入…

基于深度学习的高精度足球检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度足球检测识别系统可用于日常生活中或野外来检测与定位足球目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的足球目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型…

【Java基础学习打卡09】JRE与JDK

目录 引言一、JRE二、JDK三、JDK、JRE和JVM关系总结 引言 本文将介绍JRE、JDK是什么&#xff0c;以及JDK、JRE和JVM关系三者之间的关系。 一、JRE JRE全称为Java Runtime Environment&#xff0c;是Java应用程序的运行时环境。JRE包括Java虚拟机&#xff08;JVM&#xff09;、…

【数据结构】二叉树经典题目

1. 二叉树创建字符串 相信大部分人看了题目描述之后&#xff0c;都会和我一样一脸的懵逼。直到我看到了一个描述才恍然大悟 分为3种情况&#xff1a; 左右都为空 --省略右为空&#xff0c;左不为空 – 省略左为空&#xff0c;右不为空–不省略 这里复习一下二叉树的前序遍历…

Linux基本指令(四)

文章目录 一、新建(adduser)与删除(userdel)普通用户二、date指令三、find指令四、grep指令 一、新建(adduser)与删除(userdel)普通用户 前面我Linux登录时都是以root的身份登录的&#xff0c;从现在开始以普同用户登录&#xff0c;那么普通用户哪里来&#xff0c;是由root用户…

泰坦陨落2找不到msvcr120.dll的解决方法

msvcr120.dll是的动态链接库文件之一。它在Windows操作系统中发挥着重要的作用&#xff0c;它提供了应用程序所需的各种功能和方法。 该文件返回编译后的代码所需的支持库。msvcr120.dll包含用于C / C编译器生成的应用程序所需的重要功能&#xff0c;包括数学函数&#xff0c;…

第六节 容器(列表)

文章目录 列表掌握知识点1.1 概述1.1.1 语法格式 1.2 列表的循环遍历1.2.1 for 循环遍历列表1.2.2 while 循环遍历列表 1.3 列表的常见操作1.3.1 列表增加元素1.3.2 列表删除元素1.3.3 列表查询元素 1.4 列表的排序1.5 列表的嵌套1.6 练习 随机分班1.7 练习 判断字符结尾1.8 扩…

华为OD机试真题 JavaScript 实现【最长子字符串的长度】【2022Q4 100分】,附详细解题思路

一、题目描述 给你一个字符串s&#xff0c;字符串s首尾相连组成一个环形&#xff0c;请你在环形中找出‘o’字符出现了偶数次最长子字符串的长度。 二、输入描述 输入一串小写字母组成的字符串。 三、输出描述 输出一个整数。 四、解题思路 题目要求在给定的环形字符串中…

HTML中嵌入JavaScript代码的三种方式

第一种方式: <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>HTML中嵌入JavaScript的第一种方式</title> </head> <body> <!-- 1.要实现的功能…

Unix/Linux操作系统的最强入门科普(经典)

今天这篇文章&#xff0c;我们来聊聊操作系统&#xff08;Operating System&#xff09;。 说到操作系统&#xff0c;大家都不会陌生。我们天天都在接触操作系统——用台式机或笔记本电脑&#xff0c;使用的是windows和macOS系统&#xff1b;用手机、平板电脑&#xff0c;则是…

深度学习入门——神经网络

神经网络 神经网络是一种受到人脑神经系统启发的机器学习模型。它由一系列相互连接的人工神经元组成&#xff0c;这些神经元以层次结构排列。每个神经元接收来自上一层神经元的输入&#xff0c;并根据权重和激活函数对输入进行加权处理&#xff0c;然后将输出传递给下一层神经…

【框架源码】Spring源码解析之Bean创建源码流程

问题&#xff1a;Spring中是如何初始化单例bean的&#xff1f; 我们都知道Spring解析xml文件描述成BeanDefinition&#xff0c;解析BeanDefinition最后创建Bean将Bean放入单例池中&#xff0c;那么Spring在创建Bean的这个过程都做了什么。 Spring核心方法refresh()中最最重要…

uniapp小程序订单页面UI

前言 之前用模板写了订单页面&#xff0c;由于需求改了导致这个页面做更新麻烦&#xff0c;弄了一下午&#xff0c;索性全部删除了自己写了&#xff0c;上面的tabs用的是b-ui框架写的&#xff0c;其他的都是原生写法。 &#x1f64f;如果这篇文章对你有帮助还请收藏点赞关注&…

【计算机视觉】不仅能分割一切简单物体,而且还能高精度分割一切复杂物体的SAM升级版本HQ-SAM来了

文章目录 一、SAM 导读二、SAM 的应用场景2.1 SAM-RBox-生成旋转矩形框2.2 Prompt-Segment-Anything-生成矩形框和掩2.3 Grounded-Segment-Anything-开放数据集检测与分割2.4 segment-anything-video-视频分割2.5 Open-vocabulary-Segment-Anything-开放词典分割2.6 SegDrawer-…

快速入门 Lua 编程

以下是一个简单的 Lua 快速编程教程&#xff0c;帮助你快速入门 Lua 编程。 安装 Lua 首先&#xff0c;你需要安装 Lua。你可以从 Lua 官网&#xff08;https://www.lua.org/download.html&#xff09;下载适合你的操作系统的安装包。安装完成后&#xff0c;你可以在命令行中…

CTFHub | 命令注入

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

记录一次scala项目导入编译失败的问题

文章目录 Scala项目环境问题记录小结 Scala项目环境 Java8 scala-2.11.12 MacBook Apple m2芯片 问题记录 1、scala版本安装 我的本地环境&#xff1a; ➜ ~ java --version openjdk 11.0.18 2023-01-17 OpenJDK Runtime Environment Homebrew (build 11.0.180) OpenJDK 64-…

【Flutter】Flutter 如何实现开屏广告

文章目录 一、前言二、实现开屏广告页面三、实现广告数据的加载四、开屏广告的完整代码五、总结 一、前言 开屏广告这个功能在商业应用中非常常见&#xff0c;它可以在应用启动时向用户展示广告&#xff0c;增加应用的商业价值。 如果你想深入学习 Flutter&#xff0c;掌握更…