linux open 头文件_linux下通过共享内存和mmap实现进程间通讯

前言

最近在学习GNU/Linux内核,看到mmap的时候书上说:

mmap/munmap接口函数是用户最常用的两个系统调用接口,无论是在用户程序中分配内存、读写大文件、链接动态库文件,还是多进程间共享内存,都可以看到mmap/munmap的身影。

这句话说的很正确,虽然我们日常没有直接使用mmap,但是其实我们都间接地使用了mmap/mumap函数。

举个例子,我们使用动态链接库的时候,我们都知道,动态链接不会把动态库中的代码整合到目标文件中,相反,动态库跟目标文件独立。

那为什么运行时,程序能够获得指定的符号链接?这正是mmap的力量,程序运行时,他将保存在物理内存的动态库的内容(如果物理内存中没有,则先加载如内存)映射到自身的进程地址空间,这样符号所对应的指令数据便存在了。

(通过ldd可获取所依赖的动态库,Linux怎么获取到的,我怀疑跟ELF文件格式有关,待解答)

mmap

mmap是内存映射文件的方法

mmap将一个文件或者其它对象映射进内存。mmap在用户空间映射调用系统中作用很大。

mmap()必须以PAGE_SIZE为单位进行映射,而内存也只能以页为单位进行映射,若要映射非PAGE_SIZE整数倍的地址范围,要先进行内存对齐,强行以PAGE_SIZE的倍数大小进行映射。

头文件

函数原型

void* mmap(void* addr, size_t length,int prot,int flags,int fd,off_t offset); int munmap(void* start,size_t length);

  • addr: 用于指定映射到进程地址的起始地址,为了应用程序的可移植性,一般设为nullptr;
  • length: 表示映射到进程地址空间的大小;
  • prot: 表示设置内存映射区域的读写属性等;
  • flags: 用于设置内存映射的属性,例如共享映射、私有映射、匿名映射等;
  • fd: 文件句柄,如果不是文件映射,则置为0;
  • offset: 文件映射时的文件偏移量。

重复一遍:由于GNU/Linux中,内存分配是以页为单位的,所以length长度不足1页(默认4KB),则按1页来处理。

prot参数detail:

351d473c8a07e64498971c5087eab905.png

flags参数detail:

1a481c25a45da8c39d0de1de8aff175e.png

共享内存

共享内存Shared Memory,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。

具体来说,共享内存就是一段真实存在的物理内存,不同进程通过访问和修改该段物理内存,最终达到共享内存的目的。

PS: 共享内存不提供数据同步机制,如一个进程在写过程中,另一个进程可以进行读操作和写操作,所以需要通过信号量来解决同步问题。

创建共享内存

函数介绍

函数原型如下:

#include #include         /* For mode constants */#include            /* For O_* constants */int shm_open(const char *name, int oflag, mode_t mode);int shm_unlink(const char *name);Link with -lrt.

shm_open()创建并打开一个新的或现有的POSIX共享内存对象。POSIX共享内存对象实际上是一个句柄,它可以被与mmap共享内存相同区域的无关进程使用。

shm_unlink()函数的作用是:删除先前由shm_open()创建的对象。

函数用法

int fd = shm_open("/shm01", O_CREAT | O_RDWR, 0777);

当oflag使用O_CREAT时,mode表示创建文件时的权限,权限写法跟命令chmod一样(https://www.runoob.com/linux/linux-comm-chmod.html)。

open与shm_open区别

或许你会问:如果是创建一个文件何必使用shm_open呢?为什么不使用open?

理论上来说两个方法可以相互替换。

但是,很重要的一点是:shm_open会将文件创建在/dev/shm目录下,该目录下挂载的文件系统格式是tmpfs,该目录下的文件也只存储在内存(主存)中。如果你使用open方法在该目录下创建和打开文件其实两者就没有本质区别了。

9dffaca5eab234e82e3f6225f24219d7.png

如图所示,/dev/shm是tmpfs文件系统

进程间通讯实例

本测试用例需要依赖googletest测试框架,当然读者可以通过分别建立两个项目来实现下述实例;

实例原理

ea44d5369bfba6206033e2e07dda7ecc.png

如图所示,共享内存创建后保存在真实的物理内存中,通过mmap函数我们将该物理内存地址映射到进程地址空间中,最终实现操作共享内存的功能。

实例功能

服务端:创建共享内存,并将内存映射到进程地址空间中,然后进行定时修改内存内容。

客户端:映射共享内存到进程地址空间中,定时获取内存内容。

实例代码

服务端代码

#include #include #include #include TEST(shm_test, server) {    int fd = shm_open("/shm01", O_CREAT | O_RDWR, 0777);    // int fd = open("/dev/shm/shm01", O_CREAT | O_RDWR);    if (fd < 0) {        std::cout << "error to create or open" << std::endl;        return;    }    std::cout << "create or open ok" << std::endl;    ftruncate(fd, 4096);// 分配4KB内存    char *ptr = (char *)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);    close(fd);    char a[] = "00";    for (char k = 0; k < 26; ++k) {        memset(a, 'a' + k, 1 *sizeof(char));        strcpy(ptr, a);        sleep(1);    }    strcpy(ptr, a);    mumap((void *)ptr, 4096); // 关闭映射    exit(0);}

客户端代码

#include #include #include #include TEST(test, client) {    int fd = shm_open("/shm01", O_RDWR, 0777);    // int fd = open("/dev/shm/shm01", O_CREAT | O_RDWR);    if (fd < 0) {        std::cout << "error to open" << std::endl;        return;    }    char *ptr = (char *)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);    close(fd);    while(true) {        std::cout << ptr << std::endl;        sleep(1);    }    exit(0);}

执行结果

8f2ffd0d60da482624b19d34e0dd1f59.png

开头的z是之前保存在共享内存中的数据

可以看到客户端输出了英语字母。

遇到的问题

  1. 找不到shm_open的符号链接

答:在编译时链接rt库

  1. 使用googletest时,缺失pthread

答:链接pthread库

总结

本篇文章,我们知道了共享内存,通过共享内存和mmap我们能很轻易地完成进程间通讯(IPC Inter-Process Communication),进程间的semaphore(信号量)实现方式也是通过mmap和共享变量实现的。

文章出处:https://my.oschina.net/StupidZhe/blog/4647178

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

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

相关文章

TinyML:下一轮人工智能革命

来源&#xff1a;AI前线作者&#xff1a;Matthew Stewart译者&#xff1a;盖磊策划&#xff1a;陈思人工智能的一个趋势是正快速从“云端”走向“边缘”。TinyML 是在海量的物联网设备端微控制器上实现的人工智能&#xff0c;有望在未来几年内&#xff0c;成为人工智能在工业领…

springboot导入项目依赖报错_最详细的 Spring Boot 多模块开发与排坑指南

来源于公众未读代码 &#xff0c;作者达西呀创建项目创建一个 SpringBoot 项目非常的简单&#xff0c;简单到这里根本不用再提。你可以在使用 IDEA 新建项目时直接选择 Spring Initlalize 创建一个 Spring Boot 项目&#xff0c;也可以使用 Spring 官方提供的 Spring Boot 项目…

图书管理系统html_结自主可控数字化硕果,同方鼎欣推进基于OFD技术的数字档案管理系统研发...

01浅谈建立自主可控版式格式的重要性说起版式文档&#xff0c;相信大家首先想到的就是Adobe公司推出的PDF&#xff0c;这种格式的电子文档&#xff0c;其效果不因软硬件环境变化而变化&#xff0c;在版面、字体、字号方面可以与纸质文件保持一致&#xff0c;这就是版式文档的重…

联结你与万物的8种元素

本文经授权转载自《原理》微信公众号你不仅由元素构成&#xff0c;你其实就是元素。不同元素的原子在你的身体里&#xff0c;它们随你而动&#xff0c;它们与你一同经历成功的狂喜&#xff0c;一同承受失败的悲痛&#xff0c;也一同走过平淡的日常。当你吃下食物时&#xff0c;…

Spring中的用到的设计模式大全

spring中常用的设计模式达到九种&#xff0c;我们举例说明&#xff1a; 第一种&#xff1a;简单工厂又叫做静态工厂方法&#xff08;StaticFactory Method&#xff09;模式&#xff0c;但不属于23种GOF设计模式之一。 简单工厂模式的实质是由一个工厂类根据传入的参数&#xff…

crontab 日志_聊聊老板让我删除日志文件那些事儿

一、背景老板&#xff1a;小白&#xff0c;刚才咱们的机器告警磁盘空间不足了&#xff0c;你去定位一下原因。我&#xff1a;(......空间不足碍我屁事儿)好的&#xff0c;马上定位我&#xff1a;老板&#xff0c;太多N天前的日志文件占用了太多空间。 老板&#xff1a;你感觉你…

【专家观点】刘经南院士:北斗+5G为何能引领新基建?

来源&#xff1a;智能研究院日前&#xff0c;“第四届全球未来出行大会&#xff08;GFM2020&#xff09;”在德清召开。本次大会旨在探讨未来的城市、未来的出行、未来的汽车如何为居民提供更加经济、便捷、安全、科技友好的新出行方式。在论坛的演讲中&#xff0c;中国工程院院…

ae中心点重置工具_(精品)AE从小白到大神之路(七)-AE动画—动效常见的设计方法...

动画——动效常见的设计方法一&#xff0e;基础动画&#xff1a;1.通过物体本身的旋转/缩放/位移/不透明度等基本属性来做的一些动效属于最基础的动画效果。二&#xff0e;路径动画&#xff1a;&#xff08;1&#xff09;修剪路径动画&#xff08;前面系列案例——下载提示完成…

css 透明度_如何使用CSS实现精美视频片头制作

借助CSS所提供的动画效果&#xff0c;旋转效果除了能够制作动画及网页页面元素&#xff0c;如按钮之外&#xff0c;还可以使用CSS实现精美的动态片头的制作。本文主要介绍CSS与HTML实现精美的动画片头制作实例。如何使用CSS实现精美片头制作CSS动态片头设计实例本例设计使用烟雾…

重磅盘点:过去8年中深度学习最重要的想法

原文&#xff1a;Deep Learning’s Most Important Ideas[1]作者&#xff1a;Denny Britz&#xff08;ML 研究员&#xff0c;Google Brain 前成员&#xff09;译者&#xff1a;REN深度学习是一个瞬息万变的领域&#xff0c;层出不穷的论文和新思路可能会令人不知所措。即使是经…

ActiveMQ 发送和接收消息

一、添加 jar 包 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-all</artifactId><version>5.11.2</version> </dependency> 二、消息传递的两种形式 1、点对点&#xff1a;发送的消息只能被一个消…

机器人 蓝buff 钩_机器人要在S赛登场了?Ming韩服练起来了,这是RNG黑科技?

随着S9全球总决赛日程的逼近&#xff0c;各大战队也纷纷结束了休假&#xff0c;投入到了紧张的训练之中。对于这次S9世界赛的版本&#xff0c;应该是上中野的版本&#xff0c;因为不少战士单带型上单得到了巨大加强&#xff0c;而且中路会有一些法师英雄回归&#xff0c;总体来…

java构造器_Java类加载的过程

阅读本文约需要8分钟 大家好&#xff0c;我是你们的导师&#xff0c;经常看我朋友圈的同学应该知道&#xff0c;我每天会在微信上给大家免费提供以下服务&#xff01;1、长期为你提供最优质的学习资源&#xff01;2、给你解决技术问题&#xff01;3、每天在朋友圈里分享优质的技…

再讲卷积的本质及物理意义,解释的真幽默!

来源&#xff1a;电子工程专辑编辑 ∑Gemini分三个部分来理解&#xff1a;1&#xff0e;信号的角度2&#xff0e;数学家的理解&#xff08;外行&#xff09;3&#xff0e;与多项式的关系>>>>卷积这个东东是“信号与系统”中论述系统对输入信号的响应而提出的。因为…

分区助手扩大c盘后自动修复_磁盘分区工具,这个好用;无论调整C盘还是系统迁移...

使用傲梅分区助手安全地对磁盘进行分区安全分区注意事项1.对于重要数据&#xff0c;最好习惯定期备份。 您可以使用免费备份软件- 傲梅轻松备份进行备份。2.当傲梅分区助手正在移动数据时&#xff0c;请不要轻易地结束过程或强制关闭程序。3.在分区过程中&#xff0c;请确保您的…

c语言转义字符_C语言啊中的转义符有什么含义?

其实所谓的换行符就是回车&#xff0c;在各类编程语言中换行符是很常见的&#xff0c;而转义字符是一种特殊的字符常量。转义字符以反斜线""开头&#xff0c;后跟一个或几个字符。转义字符具有特定的含义&#xff0c;不同于字符原有的意义&#xff0c;故称“转义”字…

强化学习到底是什么,它如何运作?

强化学习是一种行为学习模型&#xff0c;由算法提供数据分析反馈&#xff0c;引导用户逐步获取最佳结果。来源丨Towards Data Science作者丨Jair Ribeiro编译丨科技行者强化学习属于机器学习中的一个子集&#xff0c;它使代理能够理解在特定环境中执行特定操作的相应结果。目前…

hihocoder1457

http://hihocoder.com/problemset/problem/1457 找不重复子串的和 topo序搞一搞&#xff0c;用父亲更新儿子节点的val&#xff0c;记得乘上节点数 //#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#…

科普天地|“GPS欺骗”如何误导自动驾驶汽车

文章来源&#xff1a;新华网&#xff0c;版权归原作者及刊载媒体所有。新华社北京11月2日电&#xff08;记者彭茜&#xff09;一辆正常行驶的自动驾驶汽车在30秒内径直蹭上了马路牙子&#xff0c;车载全球定位系统&#xff08;GPS&#xff09;、激光雷达等“高精尖”设备竟然全…

json里面的list数据取不出来_[工具]用kaggle API下载数据集

操作平台&#xff1a;colab由于是在colab&#xff0c;需要先mount google drivefrom google.colab import drive drive.mount(/content/gdrive)导到当前目录cd gdrive/My Drive/your path上传你的kaggle.json; kaggle.json下载方法&#xff1a;kaggle官网-->右上角My Accoun…