【共享内存】

2023-11-12

1 共享内存示意图

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

 


2 共享内存数据结构

struct shmid_ds {
 struct ipc_perm shm_perm; /* operation perms */
 int shm_segsz; /* size of segment (bytes) */
 __kernel_time_t shm_atime; /* last attach time */
 __kernel_time_t shm_dtime; /* last detach time */
 __kernel_time_t shm_ctime; /* last change time */
 __kernel_ipc_pid_t shm_cpid; /* pid of creator */
 __kernel_ipc_pid_t shm_lpid; /* pid of last operator */
 unsigned short shm_nattch; /* no. of current attaches */
 unsigned short shm_unused; /* compatibility */
 void *shm_unused2; /* ditto - used by DIPC */
 void *shm_unused3; /* unused */
};

3 共享内存函数(重点)

  • shmget函数:
功能:用来创建共享内存
原型 :
int shmget(key_t key, size_t size, int shmflg);
参数 :
key: 这个共享内存段名字 ;
size: 共享内存大小 ;
shmflg: 由九个权限标志构成,它们的用法和创建文件时使用的 mode 模式标志是一样的 ;
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回 -1。

 shmflg一般常用的权限位有两个:IPC_CREAT and IPC_EXCL

  • 单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回;
  • IPC_EXCL不能单独使用,一般都要配合IPC_CREAT;
  • IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回 -- 如果创建成功,对应的shm,一定是最新的.

 我们如何获得该函数的第一个参数key呢?

我们可以使用ftok函数:

用返回值接受到生成的key_t类型即可。

  • shmat函数:
功能:将共享内存段连接到进程地址空间
原型 :
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数 :
shmid: 共享内存标识
shmaddr: 指定连接的地址 ,不指定就设置位空;
shmflg: 它的两个可能取值是 SHM_RND SHM_RDONLY ,也可以设置为0;
返回值:成功返回一个指针,指向共享内存第一个节;失败返回 -1
说明:
shmaddr NULL ,核心自动选择一个地址
shmaddr 不为 NULL shmflg SHM_RND 标记,则以 shmaddr 为连接地址。
shmaddr 不为 NULL shmflg 设置了 SHM_RND 标记,则连接的地址会自动向下调整为 SHMLBA 的整数倍。公式: shmaddr -
(shmaddr % SHMLBA)
shmflg=SHM_RDONLY ,表示连接操作用来只读共享内存。
  • shmdt函数 :
功能:将共享内存段与当前进程脱离
原型 :
int shmdt(const void *shmaddr);
参数 :
shmaddr: shmat 所返回的指针 ;
返回值:成功返回 0 ;失败返回 -1 ;
注意:将共享内存段与当前进程脱离不等于删除共享内存段。
  •  shmctl函数:
功能:用于控制共享内存
原型 :
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数 :
shmid: shmget 返回的共享内存标识码
cmd: 将要采取的动作(有三个可取值)
buf: 指向一个保存着共享内存的模式状态和访问权限的数据结构 ;
返回值:成功返回 0 ;失败返回 -1。

 


4 用共享内存实现一个客户端与服务端通信的案例

comm.hpp:

#include<iostream>
#include<cerrno>
#include<cstring>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/stat.h>
#include<unistd.h>
using namespace std;

#define PATHNAME "."
#define PROJID 6666
key_t getKey()
{
    key_t key=ftok(PATHNAME,PROJID);
    if(key==-1)
    {
        cout<<"error"<<errno<<":"<<strerror(errno)<<endl;
        return 1;
    }
    return key;
}

int creatShm(size_t size,int shmflag=0)
{
    umask(0);
    int shmid=shmget(getKey(),size,IPC_CREAT | IPC_EXCL | 0666);
    if(shmid==-1)
    {
        cout<<"error"<<errno<<":"<<strerror(errno)<<endl;
        return 1;
    }
    return shmid;
}


int getShm(size_t size,int shmflag=0)
{
    int shmid=shmget(getKey(),size,IPC_CREAT );
    if(shmid==-1)
    {
        cout<<"error"<<errno<<":"<<strerror(errno)<<endl;
        return 1;
    }
    return shmid;
}


char* attachShm(int shmid)
{
    char* start=(char*)shmat(shmid,nullptr,0);
    return start;
}

void detouchShm(char* start)
{
    int n=shmdt(start);
    if(n==-1)
    {
        cout<<"error"<<errno<<":"<<strerror(errno)<<endl;
        return ;
    }
}

void delShm(int shmid)
{
    int n=shmctl(shmid,IPC_RMID,nullptr);
    if(n==-1)
    {
        cout<<"error"<<errno<<":"<<strerror(errno)<<endl;
        return ;
    }
}

server.cc:

#include<iostream>
#include"comm.hpp"


int main()
{
    //1 创建共享内存
    int shmid=creatShm(4096);

    //2 将共享内存与自己关联起来
    char* start=attachShm(shmid);

    //3 使用共享内存通信
    int cnt=0;
    while(cnt<=15)
    {
        cout<<start<<endl;
        sleep(1);
        ++cnt;
    }

    //4 解除自己与共享内存的关联
    detouchShm(start);

    //5 删除共享内存
    delShm(shmid);
    return 0;
}

client.cc:

#include<iostream>
#include"comm.hpp"


int main()
{
    //1 创建共享内存
    int shmid=getShm(4096);

    //2 将共享内存与自己关联起来
    char* start=attachShm(shmid);

    //3 使用共享内存通信
    char ch='A';
    while(ch<='Z')
    {
        start[ch-'A']=ch;
        ++ch;
        start[ch-'A']=0;
        sleep(1);
    }    
    //4 解除自己与共享内存的关联
    detouchShm(start);

    //客户端不要删掉共享内存
    return 0;
}

这样我们便能够正常运行我们的程序了,但是假如我们不小心终止了./server进程而导致共享内存没有被删除,我们可以用命令行来删除共享内存。

查看共享内存命令:

ipcs -m

删除指定共享内存:

ipcrm -m 共享内存的id

共享内存是没有互斥同步机制的,也就是说你在写数据的时候我能够直接读取数据,这个跟管道有很大区别,管道是你写完了后我再来读取数据,管道是需要互斥同步机制的,这个我们放到后面多线程再来补充。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【共享内存】 的相关文章

  • SSH,运行进程然后忽略输出

    我有一个命令可以使用 SSH 并在 SSH 后运行脚本 该脚本运行一个二进制文件 脚本完成后 我可以输入任意键 本地终端将恢复到正常状态 但是 由于该进程仍在我通过 SSH 连接的计算机中运行 因此任何时候它都会登录到stdout我在本地终
  • 为什么 Linux 没有 DirectX API?

    在考虑现代显卡的 Windows 系统上 DirectX API 的驱动程序端实现时 我想知道为什么此实现在非 Windows 系统 尤其是 Linux 上不可用 由于明显缺乏此功能 我只能假设有一个我无视的充分理由 但在我的原始理解中 我
  • 适用于 Linux 的轻量级 IDE [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 调用 printf 系统子例程在汇编代码中输出整数错误[重复]

    这个问题在这里已经有答案了 来回 在windows7控制台窗口中运行gcc s2 asm 然后生成一个exe文件 运行a exe 然后崩溃 为什么 s2 asm 代码由以下源代码生成 int m m 1 iprint m s2 asm请参考
  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了
  • 我们真的应该使用 Chef 来管理 sudoers 文件吗?

    这是我的问题 我担心如果 Chef 破坏了 sudoers 文件中的某些内容 可能是 Chef 用户错误地使用了说明书 那么服务器将完全无法访问 我讨厌我们完全失去客户的生产服务器 因为我们弄乱了 sudoers 文件并且无法再通过 ssh
  • 在centos中安装sqlite3 dev和其他包

    我正在尝试使用 cpanel 在 centos 机器上安装 sqlite dev 和其他库 以便能够编译应用程序 我对 debian 比 centos 更熟悉 我知道我需要的库是 libsqlite3 dev libkrb5 dev lib
  • 如何在 Ubuntu 中创建公共 HTML 文件夹?

    简单的问题 但由于某种原因我无法在谷歌上找到确切的答案 我在 Slicehost 上安装了全新的 Ubuntu 并且想在我的主目录中为包含一堆静态 HTML 文件的简单网站创建一个公共目录 我该怎么做呢 只是打字的问题吗mkdir publ
  • 如何在linux中以编程方式获取dir的大小?

    我想通过 C 程序获取 linux 中特定目录的确切大小 我尝试使用 statfs path struct statfs 但它没有给出确切的大小 我也尝试过 stat 但它返回任何目录的大小为 4096 请建议我如何获取 dir 的确切大小
  • 如何阻止ubuntu在使用apt安装或更新软件包时弹出“Daemons using outdatedlibraries”? [关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我最近新安装了 Ubuntu 22 04 LTS 我发现每次使用 apt 安装或更新软件包时 它都会询问我有关Which servic
  • 无需超级用户即可在 Linux 中打开 RAW 套接字

    我必须编写一个在 Linux 上运行的 ping 函数 语言是 C 所以 C 也可以 在网上搜索并查看源代码ping命令 事实证明我应该创建一个原始套接字 icmp sock socket AF INET SOCK RAW IPPROTO
  • 添加文件时运行 shell 命令

    我的 Linux 机器上有一个名为 images 的文件夹 该文件夹连接到一个网站 该网站的管理员可以向该网站添加图片 但是 当添加图片时 我想要一个命令来运行调整目录中所有图片的大小 简而言之 我想知道当新文件添加到特定位置时如何使服务器
  • 如何让R使用所有处理器?

    我有一台运行 Windows XP 的四核笔记本电脑 但查看任务管理器 R 似乎一次只使用一个处理器 如何让 R 使用全部四个处理器并加速我的 R 程序 我有一个基本系统 我使用它在 for 循环上并行化我的程序 一旦您了解需要做什么 此方
  • 从 Xlib 转换为 xcb

    我目前正在将我的一个应用程序从 Xlib 移植到 libxcb 但在查找有关我有时使用的 XInput2 扩展的信息时遇到了一些麻烦 libxcb 中有 XInput2 实现吗 如果是的话 在哪里可以找到文档 目前我在使用此功能时遇到问题
  • 内核的panic()函数是否完全冻结所有其他进程?

    我想确认内核的panic 功能和其他类似kernel halt and machine halt 一旦触发 保证机器完全冻结 那么 所有的内核和用户进程都被冻结了吗 是panic 可以被调度程序中断吗 中断处理程序仍然可以执行吗 用例 如果
  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • 配置tomat的server.xml文件并自动生成mod_jk.conf

    我在用apache 2 2 15 and tomcat6 6 0 24 on CentOS 6 4并希望使用 tomcat 服务器的功能 通过添加以下内容自动生成 mod jk conf 文件
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • 如何在 *nix 中登录时运行脚本?

    我知道我曾经知道如何做到这一点 但是 如何在 unix 中登录时运行脚本 bash 可以 From 维基百科 Bash http en wikipedia org wiki Bash 28Unix shell 29 当 Bash 启动时 它
  • 我什么时候应该编写 Linux 内核模块?

    有些人出于某种原因想要将 Linux 中的代码从用户空间移动到内核空间 很多时候 原因似乎是代码应该具有特别高的优先级 或者只是 内核空间更快 这对我来说似乎很奇怪 我什么时候应该考虑编写内核模块 有一套标准吗 我怎样才能激励将代码保存在

随机推荐

  • vue element插件this.$confirm用法(取消也可以发请求)

    场景 弹出框的两个按钮都能分别请求接口 最简单的弹出框就是 确定 取消 一般用户点击确定才会继续接下来的动作 点击取消则不做任何动作 即不会请求接口 如
  • Chromium OS初体验 就是一款Linux

    好奇 弄了一个Chromium OS for VMWare 玩玩 发现Chromium OS并非像我之前想象的一样 并非完全是一个自主研发的独立操作系统 启动 Chromium OS 时 vmware 被设置成图形模式 但一片漆黑什么都看不
  • 【OpenCV】Blob斑点检测学习笔记

    设置 SimpleBlobDetector 参数 params cv2 SimpleBlobDetector Parms 改变阈值 params minThreshold 自定义下阈值 params maxThreshold 自定义上阈值
  • stm32实现Systick的毫秒级延时和微妙级延时

    学习目标 stm32实现Systick的毫秒级延时和微妙级延时 学习内容 1 Systick 工作原理 Systick 系统定时器 是ARM Cortex M3 M4 内核的一个外设 因为所有的CM3 M4内核的单片机都带有这个定时器 这使
  • 若依微服务增强swagger增强集成knife4j

    1 项目pom xml中增加
  • iOS音视频—Shell脚本语言(语法-字符串)

    In every walk with nature one receives far more than he seeks 每一次和自然同行 都会有意外的收货 Shell脚本语言 语法 字符串 1 单引号 name wt echo name
  • 代码随想录算法训练营19期第37天

    738 单调递增的数字 代码随想录 初步思路 贪心 总结 还需要考虑遍历顺序 只有从后向前遍历才能重复利用上次比较的结果先排序 用时 45分钟 968 监控二叉树 代码随想录 初步思路 仅仅贪心好像还是不够 总结 二刷三刷再来 用时 60分
  • 【智领信创】用友 U8 cloud &亚信科技 AntDB联合产品强势来袭,0元购活动惠及陕、鲁

    近日 用友U8 cloud信创云ERP新品体验会在西安 济宁两市成功举办 用友U8 cloud 亚信科技AntDB联合产品精彩亮相 为陕 鲁两省行业客户提供领先信创解决方案的同时 也为两省客户带来极具诚意的优惠方案 U8 cloud Ant
  • 连接阿里云服务器MySql数据库

    首先先说一个坑 也是自己很久没有使用linux原因导致的 自己也是的 最近忙于工作 买了阿里云服务器之后一直都没有去弄了 感觉自己白花钱了 废话不多说了 直接进入正题 第一 肯定要看你的mysql数据库是否启动 才能确定是否能够连接 一下有
  • Outlook 突然打不开

    打开电脑正准备上班然后outlook崩了 报错建议我重装软件 问题是现在用的都是365全家桶 也没办法单独重装一个outlook 盲试了一把repair居然修好了 再后来就经常用到它T T 不是什么好事 首先有几种临时解决方法 如果时间很紧
  • mysql配置超详细教程_MySQL系列(一):超详细、非常适合入门的MySQL安装、环境配置教程...

    MySQL系列教程不定期更新 欢迎关注 一 安装环境 Windows 10 专业版 64位 二 下载MySQL 1 访问MySQL官网 网址为 http www mysql com 2 点击页面上方的 DOWMLOADS 3 选择 MySQ
  • 苹果全新iPhone首发3nm自研芯片,结果“华为发布会”冲上热搜第一…

    明敏 丰色 西风 发自 凹非寺量子位 公众号 QbitAI 就离谱 苹果发iPhone 15 结果发着发着 华为发布会 冲上了热搜第一 哪怕是iPhone 15全系告别11年闪电接口改用USB C 经典静音键从Pro系列消失 这些库克 违背
  • Android性能优化—内存优化

    一 App内存组成以及管理 Android 给每个 App 分配一个 VM 让App运行在 dalvik 上 这样即使 App 崩溃也不会影响到系统 系统给 VM 分配了一定的内存大小 App 可以申请使用的内存大小不能超过此硬性逻辑限制
  • 机器学习中关于偏差、方差和误差的理解

    在模型预测中 模型可能出现的误差来自两个主要来源 1 因模型无法表示基本数据的复杂度而造成的偏差 bias 2 因模型对训练它所用的有限数据过度敏感而造成的方差 variance 误差是测量值与真实值之间的差值 用误差衡量测量结果的准确度
  • Driver class 'org.gjt.mm.mysql.Driver' could not be found, make sure the 'MySQL' driver (jar file)

    org pentaho di core exception KettleDatabaseException Error occurred while trying to connect to the database Driver clas
  • [培训-无线通信基础-6]:信道编码(分组码、卷积吗、Polar码、LDPC码、Turbo码)

    作者主页 文火冰糖的硅基工坊 https blog csdn net HiWangWenBing 本文网址 https blog csdn net HiWangWenBing article details 118657107 目录 前言
  • Shell计算时间运行时间

    方法1 starttime date Y m d H M S 执行程序 endtime date Y m d H M S start seconds date date starttime s end seconds date date e
  • 笔试

    文章目录 前言 21 FPGA组成三要素 1 CLB 2 可编程内部互联资源 3 可编程输入输出块 22 查找表 LUT 23 锁存器 latch 触发器 24 亚稳态 25 逻辑电平 26 逻辑最小项 总结 往期精彩 前言 本文首发于微信
  • LeetCode-135.分发糖果、贪心算法

    老师想给孩子们分发糖果 有 N 个孩子站成了一条直线 老师会根据每个孩子的表现 预先给他们评分 你需要按照以下要求 帮助老师给这些孩子分发糖果 每个孩子至少分配到 1 个糖果 相邻的孩子中 评分高的孩子必须获得更多的糖果 那么这样下来 老师
  • 【共享内存】

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