Linux进程间通信——共享内存

【Linux】Linux 共享内存:高效的进程间通信 共享内存是一块可以被多个进程同时访问的内存区域,允许不同进程读取和写入同一份数据。每个进程都可以直接访问这块内存,不需要通过管道、套接字或消息队列进行数据传输。这种直接访问的特点使得共享内存成为最为高效的进程间通信机制之一,适用于需要频繁交换大量数据的场景。 阅读详情

System V共享内存

System V 标准的进程间通信方式是在OS层面专门为进程间通信设计的一个方案,通过系统调用的方式给用户提供功能。在同一个主机内的进程间通信方案叫作system V方案。
共享内存区是最快的IPC形式,一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说进程不再通过执行进入内核的系统调用来传递彼此的数据。

共享内存函数接口

shmget

功能:用来创建共享内存

int shmget(key_t key, size_t size, int shmflg);

参数:
key:这么共享内存段名字
size:共享内存大小
shmflg:由九个权限标志构成
返回值:成功返回一个非负整数,即该共享内存段的标识码,失败返回-1

shmat

功能:将共享内存段连接到进程地址空间

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

参数
shmid:共享内存标识
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个字节,失败返回-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:由shmaddr:由shmat所返回的指针
返回值:成功返回0,失败返回-1

shmctl

功能:用于控制共享内存

int shmctl (int shmid, int cmd, struct shmid_ds * buf);

shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0,失败返回-1

示例

在这个实例中我们希望在客户端(client)写入数据,服务端读取数据。共享内存只需在服务端申请一次即可,但在客户端和服务端中都要与共享内存连接。

server.c

#include "comm.h"                                                                                                "
#include <unistd.h>                                                                                                 
                                                                                                 
int main()                                                                                                 
{
// 提供一个文件地址和Id,以得到一个唯一标识值
// 并非随机值,只要地址和Id相同,就会得到相同的值
// 因此在server和client中要保证文件地址和Id相同
// 以得到同一个id                                                                                              
  key_t key = ftok(PATH_NAME, PRO_ID);                                                                                                 
  if (key < 0)                                                                                                 
  {                                                                                                 
    perror("ftok");                                                                                                 
    return 1;                                                                                                 
  }                                                                                                 
  printf("%u\n", key);                                                                                                 
  int shmid = shmget(key, SIZE, IPC_CREAT | IPC_EXCL | 0666);                                                                             
  //                如没有则创建,有则返回已有的                                                                          
  //                如没有则创建,有则报错                                                                          
  if (shmid < 0)                                                                                         
  {                                                                          
    perror("shmget");                                                                              
    return 2;                                                                                                    
  }                                                                                                 
  printf("shmid : %u\n", shmid);                                                                                      
  //sleep(10);                                                                                                
  char *mem = (char*)shmat(shmid, NULL, 0);                                                                          
  while (1)                                                                                                                      
  {                                                                                                            
    printf("%s\n", mem);                                                                          
    sleep(1);                                                                                      
  }                                                                                                         
  shmdt(mem);                                                                                       
  // 并非释放了此共享内存,只是解除共享内存与该进程的关联     
  printf("attach success\n");                                                                                 
  shmctl(shmid, IPC_RMID, NULL); 
  return 0;                                                                                                                               
}

client.c

#include "comm.h"

int main()
{
  key_t key = ftok(PATH_NAME, PRO_ID);
  if (key < 0)
  {
    perror("ftok");
    return 1;
  }
  printf("%u\n", key);
  
  int shmid = shmget(key, SIZE, IPC_CREAT);
  if (shmid < 0)
  {
    perror("shmget");
    return 2;
  }
  char *mem = (char*)shmat(shmid, NULL, 0);
  printf("client attach success\n");
  //sleep(5);
  char ch = 'A';
  while (ch <= 'Z')
  {
    mem[ch - 'A'] = ch;
    ch++;
    mem[ch - 'A'] = 0;
    sleep(2);
  }
  shmdt(mem);
  printf("client detach success\n");
  sleep(5);
  return 0;
}

comm.h

#pragma once 

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

#define PATH_NAME "./"
#define PRO_ID 0x666
#define SIZE 4096

总结

在本篇文章中对共享内存的操作主要是这几块
1.创建共享内存
流程:获取一个key值,用这个key值来获得id
2.关联共享内存
通过shmat函数
3.去关联共享内存
通过shmdt函数
4.释放共享内存
通过shmctl函数

linux进程间通信之共享内存篇 首先打开一个或者创建一个文件,并把文件长度设置为5个people结构大小,然后使用mmap函数,把该文件映射到进程空间,len设置为10个people结构的大小,请注意此时文件大小和映射到进程空间的地址并不一样,这是被允许的,进程空间设置的大小受文件大小的影响但不一定要等于文件的大小,以指定的格式向该映射内存中写入10个people的数据;由于父子进程特殊的亲缘关系,在父进程中先调用mmap(),然后调用fork,那么在fork之后,子进程继承父进程匿名映射后的地址空间,同样也继承mmap返回的地址; 阅读详情

相关推荐

linux进程间通信之共享内存

linux进程间通信,共享内存

weixin_50374599的博客 1304

Linux进程间通信:共享内存(shm)

比如:在一家餐厅中,有编号为a b c d e五张桌子,张三约了小美在c号桌一起吃饭,那么小美赴约直接到c号桌与张三共同用餐。如果张三和小美没有协议好在c桌用餐,那么他们就可能不会在同一张做桌子上吃饭,就完成不了这次约会。

m0_74985965的博客 2534

ANSYS Maxwell:创建即用型 3D 轴向磁通电机模型

Magnet Length” 是磁体的径向长度。“Magnet Thickness” 是磁体的轴向长度。为了对 AFM 进行更详细的分析,用户需要在 ANSYS Maxwell 中运行 3D FEA 分析。对于 2D 模型,它们类似于 MotorCAD 中的模型,后者对等效的直线电机进行建模。单击“确定”后,将创建一个 3D Maxwell 模型。“长度”是转子铁的轴向长度。然后需要定义定子的“磁芯”尺寸和材料。“长度”是定子铁芯的轴向长度。“转子”# 的极数必须与“定子”中定义的磁极相同。

jkh920184196的博客 1931

03进程间通信——共享内存 (shm)(✔)

共享内存其实就是通过映射的方式使得多个进程可以同时访问同一块内存,换而言之就是将一块内存 同时映射到多个进程的进程地址空间中,借此这些进程就可以通过这块内存进行数据交流。映射:把内核或者设备或者文件中的一段内存映射到进程地址空间,映射成功后,进程就可以直接利用指针去操作这一段内存 (操作映射后的指针,就相当于操作这一段内存)由于是多个进程共享一段内存,这段内存既是你的,又是我的,p1往这段内存中写入数据,实际上就是写入p2的内存中。进程P1可以映射并且操作这一段内存,同时P2也可以映射并且操作这一段内存。

qq_68915288的博客 999

保姆级教程:用MATLAB复现格拉斯哥大学FMCW雷达数据集多普勒谱(附完整代码与避坑指南)

本文提供了一份详细的MATLAB教程,指导如何复现格拉斯哥大学FMCW雷达数据集的多普勒谱分析。从环境准备、数据获取到距离压缩、MTI滤波、时频分析(STFT)以及结果后处理,涵盖了完整流程,并附有优化代码和避坑指南,特别适合雷达信号处理研究者和工程师。

weixin_28720767的博客 116

mongoDB 数据莫名其妙的没了

问题 之前没有接触过mongoDB,然后接手一个项目使用的是MongoDB,我就跟着网上的教程搭建一个MongoDB的服务,并运行起来。 一开始没有啥问题,成功的把服务与MongoDB都启动以来,运行也没有问题。但是过了几天,我再次打开时发现,以前的数据神奇的消失了。我还在想,是有什么定时清除的么,还是什么原因导致崩了然后数据就被清理了。 查找原因 第一次遇到我没有在意,重启了一下MongoDB,...

技术熊的博客小窝 1万+

【Linux】进程间通信——共享内存

例2:进程A从键盘循环获取数据并拷贝到共享内存中,进程b从共享内存中获取并打印数据。要求进程a输入一次,进程b输出一次,a不输入,b就不输出。一般给0代表可读可写,可以给SHM_RDONLY 为只读模式,其他为读写。例1:进程A向共享内存写入数据,进程B从共享内存中读取数据并显示。A(./main)未输入时,B(./test)不输出(阻塞着)而输出的时候一直输出S内的数据,没有控制,会一直循环输出。正确流程是写入一次读取一次,不写入不读取。A输入end,A,B退出。A输入一个,B读取一个。

qq_53830608的博客 2032

基于卷积神经网络的人脸识别算法

摘要:近年来,随着科学技术的不断发展,人脸识别技术日渐成熟,使得人脸识别技术的使用率不断增大。例如:门禁、ATM机、公安系统以及新兴起的人机交互等领域,都应用到了人脸识别系统。在人脸识别研究领域中,深度学习扮演着重要的角色。由于深度学习的人脸识别技术凭借其识别率高、识别快等特点,逐渐成为整个领域的主流技术。在众多深度学习算法中,以卷积神经网络为代表的人脸识别系统得到了广泛应用,主要研究内容如下:首先,通过对经典损失函数进行研究,对比每种损失函数的特点,然后根据A-Softmax函数进行改进,借助Margin

yyq2263511327的博客 1万+

共享内存shm

1 共享内存的原理 共享内存的接口 2 共享内存的特性 2.1生命周期跟随操作系统 2.2共享内存采用的是覆盖写的方式,读的时候, 是访问地址 2.3共享内存的删除特性

sy2453的博客 1869

保姆级QFIL线刷教程:从驱动安装到成功刷机的完整避坑指南(Win10/11实测)

本文提供了一份详细的QFIL线刷教程,涵盖从驱动安装到成功刷机的完整流程,特别针对Win10/11系统进行了实测。文章重点解决了EDL模式下的常见问题,如Download Fail和COM Port识别错误,并提供了实用的避坑技巧和故障排除方案,帮助用户实现零失误操作。

weixin_29245767的博客 765

深入解析 ReDoc:从零构建高性能 API 文档的终极指南

ReDoc 是一个强大的开源工具,用于将 OpenAPI 规范转换为高质量、响应式的 API 文档。本文详细介绍了如何使用 ReDoc 构建和自定义 API 文档,包括如何编写支持 OpenAPI 的 API 注解、配置 HTML 页面以加载文档,以及如何利用 ReDoc 的高级功能进行定制。通过实例代码,您将学会如何灵活地展示 API 文档,提升用户体验。无论是初学者还是经验丰富的开发者,都能从本文中获得实用的技巧与方案,帮助快速搭建符合需求的 API 文档界面。

楠搏万的博客 4631

共享内存机制——mmap和shm

共享内存是进程间通信的一种方法,常用到的有mmap和shm,下面做一个比较。 mmap机制: 在磁盘上建立一个文件,然后把文件内容映射到虚拟内存上,在每个进程的虚拟存储器里面,单独开辟一个空间来进行映射。在多进程情况下,不会对实际的物理存储器(主存)消耗太大。 即将一个文件或者其它对象映射到进程的虚拟地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一 一对映关系。 实现这样的映射关系后...

PPprogrammer的博客 3549

手把手教你学Simulink--基于储能系统的建模与仿真场景:-锂电池储能系统充放电管理策略仿真

《锂电池储能系统充放电管理的Simulink建模与仿真》摘要 本文详细介绍了使用Simulink+SimscapeElectrical对锂电池储能系统进行充放电管理策略建模的全过程。从系统结构设计入手,重点阐述了锂电池模型、充放电控制器、热管理系统等核心模块的搭建方法,并提供了完整的仿真流程。文章详细说明了如何实现荷电状态管理、温度控制和功率限制等关键策略,通过仿真分析了电池电压、电流、SoC和温度等关键指标的变化规律。最后提出了基于仿真结果的优化建议,包括参数整定、算法改进等方面,为锂电池储能系统的安全高

MHD0815的博客 1万+

【Linux】进程间通信——System V共享内存

System V是一种在Linux系统中用于进程间通信(IPC)的机制。它提供了几种不同的通信方式,包括共享内存、消息队列和信号量。System V共享内存是一种高效的进程间通信(IPC)机制,它允许多个进程共享一块物理内存区域,从而避免了数据的复制,显著提高了数据传输速率。

Renswc的博客 2486

【后量子密码】SPHINCS+ 算法(二):签名与验签(附源码分析)

本节介绍SPHINCS+ 算法的密钥生成、签名与验签。nnn:安全参数;www:Winternitz参数,WOTS+签名分解的基底;hhh:超树的高度;ddd:超树中子树的层数;kkk:FORS 树的数量;ttt:FORS 树的叶子节点数。

听雨草堂 4680

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【Linux笔记】进程间通信——system v 共享内存

共享内存是Linux系统中进程间通信(IPC)的一种方式,允许多个进程直接访问同一块物理内存区域。它的核心特点是零拷贝——数据直接在内存中共享,无需通过内核缓冲区中转,因此成为速度最快的IPC机制。共享内存是system v的一种标准,Linux内核支持这种标准,专门设计了这个模块。两个进程访问同一块物理内存,如上图共享内存通过页表映射到两个进程的地址空间,两个进程就可以看到同一块资源,进而实现进程间的通信。

GGDxianv的博客 1106

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【Linux进程间通信】共享内存

本篇博客将介绍system V共享内存

m0_74215144的博客 1114

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【Linux-进程间通信】共享内存

ipcs是一个用于查看 POSIX 系统中进程间通信 (IPC) 资源信息的命令行工具。使用-m选项可以专门查看共享内存 (shared memory) 的相关信息。常用选项描述-m显示共享内存段的信息-q显示消息队列的信息(不与-m一起使用)-s显示信号量的信息(不与-m一起使用-t显示创建时间-p显示创建者的 PID-c显示核心映像的创建者-l显示更详细的列表字段含义key用于访问共享内存段的键值。这个键是由ftok。

2202_75331338的博客 2047

Linux:进程间通信->共享内存

共享内存实现进程间通信

m0_68142120的博客 1163

Linux:进程间通信之共享内存

我们无论使用命名管道还是匿名管道,都是在文件层面上实现的通信,实际上还有基于系统层面的system v标准的进程间通信方式。因为操作系统不相信用户,所以用户使用的时候只能通过调用的方式system v提供的主流方式有三个:1.共享内存 2.消息队列(有些落伍)3.信号量前两个以传送数据为目的,第三个以实现进程间同步后者互斥为目的。

Au_ust的博客 1090

【Linux进程间通信】深入探索:Linux下的命名管道与System V共享内存

在Linux操作系统中,进程间通信(IPC)是一个至关重要的概念,它允许不同的进程之间进行数据交换和同步。随着现代操作系统的日益复杂,进程间通信的重要性也日益凸显。在众多IPC机制中,命名管道和System V共享内存无疑是两种最为常见且强大的工具

EterNity_TiMe_的计算机学习之路 3117

【Linux】进程间通信之共享内存

为什么进程间需要通信? 1、数据传输:一个进程需要将它的数据发送给另一个进程。 2、资源共享:多个进程之间享受同样的资源 3、通知事件:一个进程需要向另一个或另一组进程发送消息,通知它们发生了某种事件。 4、进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够即使知道它的状态改变。 Linux进程间通信(IPC)

Scenlyf的博客 2903

Linux——进程间通信之SystemV共享内存

SystemV通信一般包括三种:共享内存、消息队列和信号量。共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到 内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

m0_75262940的博客 920
上一篇: Linux进程间通信——命名管道
下一篇: Linux进程间通信——信号量
JayceSun449
博客等级 码龄5年 554粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JayceSun449

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值