进程通信方式---共享映射区(无血缘关系用的)

5.共享映射区(无血缘关系用的)

文章目录

    • 5.共享映射区(无血缘关系用的)
      • 1.概述
      • 2.mmap&&munmap函数
      • 3.mmap注意事项
      • 4.mmap实现进程通信
        • 父子进程
          • 练习
        • 无血缘关系
      • 5.mmap匿名映射区

1.概述

  • 原理:共享映射区是将文件内容映射到进程的地址空间中,使得多个进程可以通过访问这个共享的内存区域来实现通信。进程对映射区域的操作就如同对文件进行操作一样,这些操作会直接反映在文件和其他共享该映射区域的进程中。

  • 示例场景:多个进程需要共同操作一个配置文件,通过将该配置文件映射到共享映射区,进程可以直接在内存中读取和修改配置信息,而不需要频繁地进行文件 I/O 操作。

  • 优点:结合了内存操作的高效性和文件存储的持久性;可以方便地在不相关的进程之间实现通信,只要它们能访问到同一个文件。

  • 缺点:对文件的操作需要注意同步问题,否则可能导致数据不一致;文件大小可能会限制共享映射区的大小。

**存储映射I/O(Memory-mapped l/O)使一个磁盘文件与内存存储空间中的一个缓冲区相映射。**于是当从缓冲区中取数据,就相当于读文件中的相应字节。于此类似,将数据存入缓冲区,则相应的字节就自动写入文件。这样,就可在不适用read和write函数的情况下,使用地址(指针)完成I/O操作。

使用这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实
现。

2.mmap&&munmap函数

创建共享内存映射

include<sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);	

参数:

  • addr: 指定映射区的首地址。通常传NULL,表示让系统自动分配

  • length:共享内存映射区的大小。(<= 文件的实际大小)

  • prot: 共享内存映射区的读写属性。PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE

  • flags: 标注共享内存的共享属性,共享就是对文件的修改会写回磁盘,私有就不会写回磁盘。MAP_SHARED、MAP_PRIVATE

  • fd: 用于创建共享内存映射区的那个文件的 文件描述符,就是要映射到内存的文件

  • offset:默认0,表示映射文件全部。偏移位置,从哪里开始映射。需是 4k 的整数倍

返回值:

成功:映射区的首地址

失败:MAP_FAILED (void*(-1)), errno----就是把-1强转为void *了

释放共享内存映射

int munmap(void *addr, size_t length);

参数

addr:mmap 的返回值,共享内存映射首地址

length:大小

返回值

成功0,失败-1

函数使用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>void sys_err(const char *str)
{perror(str);exit(1);
}int main(int argc, char *argv[])
{char *p = NULL;int fd;fd = open("testmap", O_RDWR|O_CREAT|O_TRUNC, 0644);     // 创建文件用于创建映射区if (fd == -1)sys_err("open error");
/*lseek(fd, 10, SEEK_END);            // 两个函数等价于 ftruncate()函数write(fd, "\0", 1);
*/ftruncate(fd, 20);                  // 需要借助写权限,才能够对文件进行拓展int len = lseek(fd, 0, SEEK_END);p = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED) {sys_err("mmap error");}// 使用 p 对文件进行读写操作.strcpy(p, "hello mmap");            // 写操作printf("----%s\n", p);              // 读操作int ret = munmap(p, len);           // 释放映射区if (ret == -1) {sys_err("munmap error");}return 0;
}

3.mmap注意事项

思考 :

  1. 可以open的时候O_CREAT一个新文件来创建映射区吗 ?

  2. 如果open时O_RDONLY,mmap时PROT参数指定PROT_READ|PROT_WRITE会怎样 ?

  3. 文件描述符先关闭,对mmap映射有没有影响 ?

  4. 如果文件偏移量为1000会怎样 ?

  5. 对mem越界操作会怎样?

  6. 如果mem++,munmap可否成功 ?

  7. mmap什么情况下会调用失败 ?

    很多参数都会导致失败

  8. 如果不检测mmap的返回值,会怎样?

    会死得很惨

使用注意事项:

  1. 用于创建映射区的文件大小为 0,却指定非0大小创建映射区,出 “总线错误”。
  2. 用于创建映射区的文件大小为 0,也指定0大小创建映射区, 出 “无效参数”。
  3. 用于创建映射区的文件读写属性为,只读,映射区属性为 读、写。 出 “无效参数”; 文件和映射区都是只读的是可以的;文件只有写权限,映射区只有写权限也会报错。(2答案)
  4. 创建映射区,需要read权限。当访问权限指定为 “共享”MAP_SHARED是, mmap的读写权限应该 <=文件的open权限。 映射区只写不行。
  5. 文件描述符fd,在mmap创建映射区完成即可关闭。后续访问文件,用 地址访问。(3答案)
  6. offset 必须是 4096的整数倍。(MMU 映射的最小单位 4k )(4答案)
  7. 对申请的映射区内存,不能越界访问。 (5答案)
  8. 读写都没问题,但是munmap会失败,munmap用于释放的 地址,必须是mmap申请返回的地址。(6答案)
  9. 映射区访问权限为 “私有”MAP_PRIVATE, 对内存所做的所有修改,只在内存有效,不会反应到物理磁盘上。
  10. 映射区访问权限为 “私有”MAP_PRIVATE, 只需要open文件时,文件有读权限,用于创建映射区即可。

image-20241218222315367

mmap函数的保险调用方式:

1. fd = open("文件名", O_RDWR);
2. mmap(NULL, 有效文件大小, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

4.mmap实现进程通信

父子进程

父子等有血缘关系的进程之间也可以通过mmap建立的映射区来完成数据通信。

但相应的要在创建映射区的时候指定对应的标志位参数flags:

MAP_PRIVATE:(私有映射)父子进程各自独占映射区;

MAP_SHARED:(共享映射) 父子进程共享映射区;

结论:

父子进程共享:1. 打开的文件 2.mmap建立的映射区(但必须要使用MAP_SHARED)

流程:

父子进程使用 mmap 进程间通信:

1.父进程 先 创建映射区。 open( O_RDWR) mmap( MAP_SHARED );

2.指定 MAP_SHARED 权限

3.fork() 创建子进程。

4.一个进程读, 另外一个进程写。

练习

练习:父进程创建映射区,然后fork子进程,子进程修改映射区内容,而后,父进程读取映射区内容,查验是
否共享

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>int var = 100;int main(void)
{int *p;pid_t pid;int fd = open("temp", O_RDWR);//p = (int *)mmap(NULL, 40, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);p = (int *)mmap(NULL, 490, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//p = (int *)mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 私有的不行if(p == MAP_FAILED){		//注意:不是p == NULLperror("mmap error");exit(1);}close(fd);pid = fork();				//创建子进程if(pid == 0){*p = 7000;               // 写共享内存var = 1000;printf("child, *p = %d, var = %d\n", *p, var);} else {sleep(1);printf("parent, *p = %d, var = %d\n", *p, var);     // 读共享内存wait(NULL);int ret = munmap(p, 4);				//释放映射区if (ret == -1) {perror("munmap error");exit(1);}}return 0;
}
无血缘关系

流程: 【要求会写】

1.两个进程 打开同一个文件,创建映射区。

2.指定flags 为 MAP_SHARED。

3.一个进程写入,另外一个进程读出。

【注意】:无血缘关系进程间通信。

​ mmap:数据可以重复读取。

​ fifo:数据只能一次读取。

读端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>struct student {int id;char name[256];int age;
};void sys_err(const char *str)
{perror(str);exit(1);
}int main(int argc, char *argv[])
{struct student stu;struct student *p;int fd; fd = open("test_map", O_RDONLY);if (fd == -1)sys_err("open error");p = mmap(NULL, sizeof(stu), PROT_READ, MAP_SHARED, fd, 0);if (p == MAP_FAILED)sys_err("mmap error");close(fd);while (1) {printf("id= %d, name=%s, age=%d\n", p->id, p->name, p->age);usleep(10000);}munmap(p, sizeof(stu));return 0;
}

写端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>struct student {int id;char name[256];int age;
};void sys_err(const char *str)
{perror(str);exit(1);
}int main(int argc, char *argv[])
{struct student stu = {1, "xiaoming", 18};struct student *p;int fd; //    fd = open("test_map", O_RDWR|O_CREAT|O_TRUNC, 0664);fd = open("test_map", O_RDWR);if (fd == -1)sys_err("open error");ftruncate(fd, sizeof(stu));p = mmap(NULL, sizeof(stu), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED)sys_err("mmap error");close(fd);while (1) {memcpy(p, &stu, sizeof(stu));stu.id++;sleep(2);}munmap(p, sizeof(stu));return 0;
}

5.mmap匿名映射区

匿名映射:只能用于 血缘关系(父子)进程间通信。

p = (int *)mmap(NULL, 40, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

映射区大小想要多少写多少

权限想要啥写啥

文件描述符的地方传-1

flags要 | 下面提到的两个宏

image-20241218224059685

/dev/zero 从这个文件里面拿数据可以随便拿,想要多大拿多大的数据,只不过读出来都是文件空洞

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

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

相关文章

《云原生安全攻防》-- K8s安全框架:认证、鉴权与准入控制

从本节课程开始&#xff0c;我们将来介绍K8s安全框架&#xff0c;这是保障K8s集群安全比较关键的安全机制。接下来&#xff0c;让我们一起来探索K8s安全框架的运行机制。 在这个课程中&#xff0c;我们将学习以下内容&#xff1a; K8s安全框架&#xff1a;由认证、鉴权和准入控…

day08-别名-重定向-去重排序等

1.重复用touch命令创建同一份文件&#xff0c;会修改文件的时间戳。 alias命令&#xff1a; 别名 查看已有别名&#xff1a;alias [rootoldboy ~]# alias alias cpcp -i alias egrepegrep --colorauto alias fgrepfgrep --colorauto alias grepgrep --colorauto alias l.ls…

Qt WORD/PDF(四)使用 QAxObject 对 Word 替换(QWidget)

关于QT Widget 其它文章请点击这里: QT Widget 国际站点 GitHub: https://github.com/chenchuhan 国内站点 Gitee : https://gitee.com/chuck_chee 姊妹篇: Qt WORD/PDF&#xff08;一&#xff09;使用 QtPdfium库实现 PDF 操作 Qt WORD/PDF&#xff08;二…

设计一个基础JWT的多开发语言分布式电商系统

在设计一个分布式电商系统时&#xff0c;保证系统的可扩展性、性能以及跨语言的兼容性是至关重要的。随着微服务架构的流行&#xff0c;越来越多的电商系统需要在多个服务间共享信息&#xff0c;并且保证服务的安全性。在这样的场景下&#xff0c;JSON Web Token&#xff08;JW…

实践分享 | 公共数据金融应用的理论探索与实践研究—以人民币银行结算账户数据应用为例

摘要:公共数据具有高权威性、高准确性、高价值性以及高应用性的特点,实现公共数据的金融应用对更好服务实体经济、防控金融风险和提升金融服务水平具有重要现实意义。本文从理论探索与实践研究两个层面分析了公共数据金融应用的具体问题,一方面探索性的给出了公共数据金融应…

Node的学习以及学习通过Node书写接口并简单操作数据库

Node的学习 Node的基础上述是关于Node的一些基础&#xff0c;总结的还行&#xff1b; 利用Node书写接口并操作数据库 1. 初始化项目 创建新的项目文件夹&#xff0c;并初始化 package.json mkdir my-backend cd my-backend npm init -y2. 安装必要的依赖 安装Express.js&…

计算机视觉中的特征提取算法

摘要&#xff1a; 本文聚焦于计算机视觉中的特征提取算法&#xff0c;深入探讨尺度不变特征变换&#xff08;SIFT&#xff09;算法。详细阐述 SIFT 算法的原理&#xff0c;包括尺度空间构建、关键点检测、方向分配与特征描述子生成等核心步骤。通过 C#、Python 和 C 三种编程语…

MySQL 主从复制与 Binlog 深度解析

目录 1. Binlog的工作原理与配置2. 主从复制的设置与故障排除3. 数据一致性与同步延迟的处理 小结 MySQL的binlog&#xff08;二进制日志&#xff09;和主从复制是实现数据备份、容灾、负载均衡以及数据同步的重要机制。在高可用性架构和分布式数据库设计中&#xff0c;binlog同…

排队论、负载均衡和任务调度关系

目录 排队论、负载均衡和任务调度关系 一、排队论 二、负载均衡 三、任务调度 四、总结 排队论、负载均衡和任务调度关系 排队论为负载均衡和任务调度提供了数学理论和方法支持 排队论、负载均衡和任务调度是三个相关但不同的概念。以下是对这三个概念的详细解释和它们之…

java版询价采购系统 招投标询价竞标投标系统 招投标公告系统源码

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

景联文科技入选中国信通院发布的“人工智能数据标注产业图谱”

近日&#xff0c;由中国信息通信研究院、中国人工智能产业发展联盟牵头&#xff0c;联合中国电信集团、沈阳市数据局、保定高新区等70多家单位编制完成并发布《人工智能数据标注产业图谱》。景联文科技作为人工智能产业关键环节的代表企业&#xff0c;入选图谱中技术服务板块。…

【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut、QT)第三期

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第二期3【小沐…

实景视频与模型叠加融合?

[视频GIS系列]无人机视频与与实景模型进行实时融合_无人机视频融合-CSDN博客文章浏览阅读1.5k次&#xff0c;点赞28次&#xff0c;收藏14次。将无人机视频与实景模型进行实时融合是一个涉及多个技术领域的复杂过程&#xff0c;主要包括无人机视频采集、实景模型构建、视频与模型…

MySQL通过binlog日志进行数据恢复

记录一次阿里云MySQL通过binlog日志进行数据回滚 问题描述由于阿里云远程mysql没有做安全策略 所以服务器被别人远程攻击把数据库给删除&#xff0c;通过查看binlog日志可以看到进行了drop操作&#xff0c;下面将演示通过binlog日志进行数据回滚操作。 1、查询是否开始binlog …

IDEA 修改格式化仅格式化本次改动代码

最近总是发现格式化的时候会格式化文件所有代码&#xff0c;提交Git 后再看提交日志&#xff0c;就很不清晰。修改方式如下 中文&#xff1a; 格式化代码快捷键[中文配置]&#xff1a; 英文&#xff1a; 格式化代码快捷键[英文配置]&#xff1a;

el-table ToggleRowSelection实现取消选中没效果(virtual-scroll)

场景&#xff1a; 就是在虚拟列表el-table选中之后 点击查询 默认之前选中的 现象&#xff1a; 就是实现选中&#xff0c; 但是无法去除勾选等等 问题发现&#xff1a; 看定位的数据 有多个一样的&#xff0c;我想着勾选之前 先去掉勾选 &#xff0c;但是没效果或者说“相同的…

【含开题报告+文档+PPT+源码】基于微信小程序的点餐系统的设计与实现

开题报告 随着互联网技术的日益成熟和消费者生活水平与需求层次的显著提升&#xff0c;外卖点餐平台在中国市场上迅速兴起并深深植根于民众日常生活的各个角落。这类平台的核心在于构建了一个基于互联网的强大订餐服务系统&#xff0c;它无缝整合了餐饮商户资源与广大消费者的…

解决 MyBatis 中空字符串与数字比较引发的条件判断错误

问题复现 假设你在 MyBatis 的 XML 配置中使用了如下代码&#xff1a; <if test"isCollect ! null"><choose><when test"isCollect 1">AND exists(select 1 from file_table imgfile2 where task.IMAGE_SEQimgfile2.IMAGE_SEQ and im…

SpringBoot 手动实现动态切换数据源 DynamicSource (中)

大家好&#xff0c;我是此林。 SpringBoot 手动实现动态切换数据源 DynamicSource &#xff08;上&#xff09;-CSDN博客 在上一篇博客中&#xff0c;我带大家手动实现了一个简易版的数据源切换实现&#xff0c;方便大家理解数据源切换的原理。今天我们来介绍一个开源的数据源…

ASCII码简介以及在php中的使用

什么是 ASCII&#xff1f; ASCII&#xff08;American Standard Code for Information Interchange&#xff0c;美国信息交换标准代码&#xff09;是一种字符编码标准&#xff0c;用于在计算机、通信设备及其他设备中表示文字、符号和控制信息。它最早于 1963 年由美国国家标准…