linux进程间通信之共享内存(mmap,shm_open)

news2024/10/7 18:22:50

         共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进 程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内存连接到他们自己的地址空间中,所有的进程都可以访问共享内存中的地址。如果某个 进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。 Linux 操作系统的进程通常使用的是虚拟内存,虚拟内存空间是有由物理内存映射而来的。System V 共 享内存能够实现让两个或多个进程访问同一段物理内存空间,达到数据交互的效果。

共享内存和其他进程间数据交互方式相比,有以下几个突出特点:
        1.速度快,因为共享内存不需要内核控制,所以没有系统调用。而且没有向内核拷贝数据的过程,所以效率和前面几个相比是最快的,可以用来进行批量数据的传输,比如图片。
        2. 没有同步机制,需要借助 Linux 提供其他工具来进行同步,通常使用信号灯。
使用共享内存的步骤:
1. 调用 shmget() 创建共享内存段 id
2. 调用 shmat() id 标识的共享内存段加到进程的虚拟地址空间,
3. 访问加入到进程的那部分映射后地址空间,可用 IO 操作读写。

        在Linux系统中,有多种方式可以实现共享内存,其中一种是使用POSIX共享内(posix_shm)。POSIX共享内存有两种方法:

1.内存映射文件

        先用open函数打开一个文件,然后调用mmap函数把得到的描述符映射到当前进程地址空间中。这种方式访问速度相对较慢,因为需要内核同步或异步更新到文件系统中。

(1)代码

#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <unistd.h>  
  
int main() {  
    // 打开文件  
    int fd = open("example.txt", O_RDWR);  
    if (fd == -1) {  
        perror("Error opening file");  
        exit(EXIT_FAILURE);  
    }  
  
    // 获取文件大小  
    struct stat sb;  
    if (fstat(fd, &sb) == -1) {  
        perror("Error getting the file size");  
        exit(EXIT_FAILURE);  
    }  
    off_t length = sb.st_size; // 文件大小,单位是字节  
  
    // 映射内存到进程的地址空间  
    char* map = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
    if (map == MAP_FAILED) {  
        perror("Error mmapping the file");  
        exit(EXIT_FAILURE);  
    }  
  
    // 打印映射的内存内容,即文件内容  
    for (off_t i = 0; i < length; i++) {  
        printf("%c", map[i]); // 打印每个字符,即文件内容  
    }  
    printf("\n");  
  
    // 释放内存映射和文件描述符  
    if (munmap(map, length) == -1) {  
        perror("Error un-mmapping the file");  
        exit(EXIT_FAILURE);  
    }  
    close(fd);  
    return 0;  
}

(2)注解

  • open函数用于打开文件,其返回值是文件描述符。如果打开失败,则返回-1。第二个参数O_RDWR表示以读写模式打开文件。
  • fstat函数用于获取文件的大小,其返回值是stat结构体,其中st_size成员表示文件大小(单位是字节)。如果获取失败,则返回-1。
  • mmap函数用于将文件映射到进程的地址空间。第一个参数是映射区域的起始地址,通常为NULL。第二个参数是映射区域的长度。第三个参数是保护标志,这里设置为读、写和共享(可读、可写、可被其他进程共享)。第四个参数是映射对象的类型,这里设置为共享内存。第五个参数是文件描述符。第六个参数是文件映射的偏移量。如果映射成功,则返回映射区域的指针;否则返回MAP_FAILED。
  • munmap函数用于释放内存映射。第一个参数是映射区域的指针。第二个参数是映射区域的长度。如果释放成功,则返回0;否则返回-1。

2.共享内存对象

        先用shm_open打开一个Posix IPC名字(也可以是文件系统中的一个路径名),然后调用mmap将返回的描述符映射到当前进程的地址空间。

(1)代码

#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <unistd.h>  
  
#define SHM_SIZE 1024  // 共享内存大小  
  
int main() {  
    int fd;  
    void *map_ptr;  
  
    // 打开共享内存对象,以读写模式打开,不创建新对象,如果对象不存在则返回-1  
    fd = shm_open("/Posix IPC", O_RDWR | O_CREAT, 0666);  
    if (fd == -1) {  
        perror("shm_open");  
        exit(EXIT_FAILURE);  
    }  
  
    // 调整共享内存对象的大小,这里将其设置为1024字节  
    if (ftruncate(fd, SHM_SIZE) == -1) {  
        perror("ftruncate");  
        exit(EXIT_FAILURE);  
    }  
  
    // 将共享内存对象的描述符映射到当前进程的地址空间,map_ptr指向的就是这块内存的起始地址  
    map_ptr = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
    if (map_ptr == MAP_FAILED) {  
        perror("mmap");  
        exit(EXIT_FAILURE);  
    }  
  
    // 现在可以在map_ptr指向的内存区域进行读写操作了,这就像操作普通的内存一样简单  
    // ... 写入数据到 map_ptr 指向的内存区域 ...  
    // ... 从 map_ptr 指向的内存区域读取数据 ...  
  
    // 当进程不再需要访问共享内存时,可以通过调用munmap来撤销内存映射,参数是map_ptr和映射的长度  
    if (munmap(map_ptr, SHM_SIZE) == -1) {  
        perror("munmap");  
        exit(EXIT_FAILURE);  
    }  
  
    // 关闭共享内存对象的描述符,然后删除该对象,参数是fd和0,表示删除成功返回0,否则返回-1  
    if (close(fd) == -1) {  
        perror("close");  
        exit(EXIT_FAILURE);  
    }  
    if (shm_unlink("/my_shm") == -1) {  
        perror("shm_unlink");  
        exit(EXIT_FAILURE);  
    }  
    return 0;  
}

 (2)注解

  • shm_open函数用于打开或创建共享内存对象。第一个参数是对象名,第二个参数是打开模式(这里使用读写模式),第三个参数是权限设置(这里设置为0666,表示所有用户都可以读写这个对象)。如果对象不存在,shm_open会创建一个新对象。如果创建成功,shm_open会返回一个文件描述符。如果失败,返回-1。
  • ftruncate函数用于调整共享内存对象的大小。第一个参数是文件描述符,第二个参数是新的文件大小。这里将文件大小设置为1024字节。如果成功,ftruncate返回0;否则返回-1。
  • mmap函数用于将共享内存对象的描述符映射到当前进程的地址空间。第一个参数是映射区域的起始地址(通常为NULL),第二个参数是映射区域的长度,第三个参数是保护标志(这里设置为读、写和共享),第四个参数是映射对象的类型(这里设置为共享内存),第五个参数是文件描述符,第六个参数是文件映射的偏移量。如果映射成功,mmap返回映射区域的指针;否则返回MAP_FAILED。

3.总结

        在使用共享内存时,需要注意同步问题。因为多个进程可以同时操作共享内存,可能导致数据不一致。互斥锁和信号量等同步机制可以解决这个问题。

        共享内存是一种非常有效的进程间通信方式,尤其适用于大数据量的传输和频繁的通信需求。但是,使用共享内存时需要注意同步和数据一致性问题。

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

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

相关文章

信号的机制——信号处理函数的注册

在 Linux 操作系统中&#xff0c;为了响应各种各样的事件&#xff0c;也是定义了非常多的信号。我们可以通过 kill -l 命令&#xff0c;查看所有的信号。 # kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS …

【Spring】加载properties文件

文章目录 在Spring Context中加载properties文件测试总结 在Spring Context中加载properties文件 分为三步&#xff0c;如下图所示&#xff1a; 完整代码&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.…

【Linux】U盘安装的cfg引导文件配置

isolinux.cfg文件 default vesamenu.c32 timeout 600display boot.msg# Clear the screen when exiting the menu, instead of leaving the menu displayed. # For vesamenu, this means the graphical background is still displayed without # the menu itself for as long …

计算机是如何工作的(简单介绍)

目录 一、冯诺依曼体系 二、CPU基本流程工作 逻辑⻔ 电⼦开关——机械继电器(Mechanical Relay) ⻔电路(Gate Circuit) 算术逻辑单元 ALU&#xff08;Arithmetic & Logic Unit&#xff09; 算术单元(ArithmeticUnit) 逻辑单元(Logic Unit) ALU 符号 寄存器(Regis…

java:IDEA中的Scratches and Consoles

背景 IntelliJ IDEA中的Scratches and Consoles是一种临时的文件编辑环境&#xff0c;用于写一些文本内容或者代码片段。 其中&#xff0c;Scratch files拥有完整的运行和debug功能&#xff0c;这些文件需要指定编程语言类型并且指定后缀。 举例&#xff1a;调接口 可以看到…

Unity——URP相机详解

2021版本URP项目下的相机&#xff0c;一般新建一个相机有如下组件 1:Render Type(渲染类型) 有Base和Overlay两种选项&#xff0c;默认是Base选项 Base:主相机使用该种渲染方式&#xff0c;负责渲染场景中的主要图形元素 Overlay&#xff08;叠加&#xff09;:使用了Oveylay的…

Python大数据之linux学习总结——day09_hive函数

hive函数 函数分类标准[重点] 知识点: 原生分类标准: 内置函数 和 用户定义函数(UDF,UDAF,UDTF)分类标准扩大化: 本来&#xff0c;UDF 、UDAF、UDTF这3个标准是针对用户自定义函数分类的&#xff1b; 但是&#xff0c;现在可以将这个分类标准扩大到hive中所有的函数&#…

vue项目如何防范XSS攻击?

场景&#xff1a; 前后端交互的过程中&#xff0c;前端使用v-html或者{{}}渲染时&#xff0c;网页自动执行其恶意代码&#xff0c;如页面弹窗、跳转到钓鱼网站等 解决方案&#xff1a; 先说解决方式&#xff0c;其原理下文解释. 由于我是vue项目所以用的是vue-dompurify-html这…

大数据基础设施搭建 - Hadoop

文章目录 一、下载安装包二、上传压缩包三、解压压缩包四、配置环境变量五、测试Hadoop5.1 测试hadoop命令5.2 测试wordcount案例5.2.1 创建wordcount输入文本信息5.2.2 执行程序5.2.3 查看结果 六、分发压缩包到集群中其他机器6.1 分发压缩包6.2 解压压缩包6.3 配置环境变量 七…

行情分析——加密货币市场大盘走势(11.17)

大机构拉高出货&#xff0c;放心大胆干&#xff0c;笔者手上空单一直拿着&#xff0c;继续等待大饼下跌。 空单策略&#xff1a;入场37000附近 止盈34000-32500 止损39000 以太按照预期回调&#xff0c;继续盈利中&#xff0c;等待继续下跌。没有入场的可以入场&#xff0c;重…

你知道什么是Oracle嘛

文章目录 Oracle数据简介环境准备安装配置安装Oracle设置Oracle开机自启Oracle核心概念创建用户修改用户密码用户授权查看用户 数据备份总结 Oracle数据简介 Oracle Database&#xff0c;又名Oracle RDBMS&#xff0c;或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它…

DDD落地:从腾讯视频DDD重构之路,看DDD极大价值

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#x…

Python 如何实现 Mediator 中介者设计模式?什么是中介者设计模式?Python 设计模式示例代码

什么是中介者设计模式&#xff1f; 中介者&#xff08;Mediator&#xff09;设计模式是一种行为型设计模式&#xff0c;其主要目的是通过将对象之间的直接交互转变为通过中介者对象进行的间接交互&#xff0c;从而减少对象之间的耦合度。中介者模式通过集中控制对象之间的通信…

【基础算法】筛质数

文章目录 问题描述解决方法朴素筛法线性筛法 问题描述 给定一个正整数 n n n&#xff0c;请你求出 1 ∼ n 1∼n 1∼n 中质数的个数。 输入格式 共一行&#xff0c;包含整数 n。 输出格式 共一行&#xff0c;包含一个整数&#xff0c;表示 1∼n 中质数的个数。 数据范围 …

关于python中内存分配的问题,运行一些操作可能会导致为新结果分配内存,用Python的id()函数演示

一、考虑背景&#xff1a; 一般在python中不会考虑像C中的内存问题&#xff0c;但是在一些高级应用中会考虑&#xff0c;例如有一个特别特别大的矩阵&#xff0c;最好不要不断的赋值&#xff0c;导致内存问题产生。 二、python中的id&#xff1a; 在python中有个id&#xff…

Postman:API测试之Postman使用完全指南

Postman是一个可扩展的API开发和测试协同平台工具&#xff0c;可以快速集成到CI/CD管道中。旨在简化测试和开发中的API工作流。 Postman工具有Chrome扩展和独立客户端&#xff0c;推荐安装独立客户端。 Postman有个workspace的概念&#xff0c;workspace分personal和team类型…

Java JVM虚拟机

加载字节码文件.class 1字节一般为8位 字节码结构: 第一部分 4字节 cafebaby 第二部分 版本号 00 00 00 32, 第三部分 常量数量 count 第四部分常量池 常量类型表示: 继承关系改变 1.1以后 后面是属性方法 等参数 通过javap 反编译class ,javap xx.class javap -c xxx.…

redis实战篇(2)

优惠卷秒杀 通过本章节&#xff0c;我们可以学会Redis的计数器功能&#xff0c; 结合Lua完成高性能的redis操作&#xff0c;同时学会Redis分布式锁的原理&#xff0c;包括Redis的三种消息队列 3、优惠卷秒杀 3.1 -全局唯一ID 每个店铺都可以发布优惠券&#xff1a; 当用户抢…

京东数据采集与挖掘(京东大数据):2023年10月京东冰箱品牌销售排行榜

鲸参谋监测的京东平台10月份冰箱市场销售数据已出炉&#xff01; 10月份&#xff0c;冰箱市场的销售额有小幅上涨。鲸参谋数据显示&#xff0c;在京东平台上&#xff0c;今年10月冰箱市场的销量为94万&#xff0c;销售额将近23亿&#xff0c;同比增长超过1%。从价格上看&#x…

【Java 进阶篇】揭秘 JQuery 广告显示与隐藏:打造令人惊艳的用户体验

在当今互联网时代&#xff0c;广告已经成为网页中不可忽视的一部分。然而&#xff0c;如何通过巧妙的交互设计&#xff0c;使广告既能吸引用户的眼球&#xff0c;又不会给用户带来干扰&#xff0c;成为了许多前端开发者需要思考的问题之一。在这篇博客中&#xff0c;我们将深入…