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

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 == NULL
        perror("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 从这个文件里面拿数据可以随便拿,想要多大拿多大的数据,只不过读出来都是文件空洞

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Redis篇】Set和Zset 有序集合基本使用

目录 Set 基本命令 sadd SMEMBERS SISMEMBER SCARD 返回值&#xff1a; SPOP SMOVE SREM 集合间操作 交集&#xff1a; 并集&#xff1a; 差集&#xff1a; ​编辑 内部编码 使用场景&#xff1a; Zset 有序集合 Zset基本命令 ZADD ZCARD ZCOUNT ZRANGE …

SAP自定义权限对象

一、创建域和数据元素 SE11 二、创建权限字段 SU20 关联数据元素ZAPP 三、创建权限对象 SU21 关联权限字段ZAPP 四、新建程序&#xff0c;加入权限对象 SE38 在程序中增加以下块 AUTHORITY-CHECK OBJECT Z_BC_APP ID ZAPP FIELD 01. IF sy-subrc EQ 0. ENDIF. 五、…

linux0.11源码分析第二弹——setup.s内容

&#x1f680; 前言 继上篇博客分享了boot文件的内容后&#xff0c;本篇博客进而来到第二个文件&#xff1a; setup.s &#xff0c;对应了《linux源码趣读》的第5~8回。这部分的功能主要就是做了 三件事 &#xff0c;第一件事是做代码搬运和临时变量存放&#xff0c;第二件事是…

Halcon中histo_2dim(Operator)算子原理及应用详解

在Halcon中&#xff0c;histo_2dim算子是一个用于计算双通道灰度值图像的直方图的工具。以下是对该算子的原理及应用的详细解释&#xff1a; 一、原理 histo_2dim算子的函数原型为&#xff1a;histo_2dim(Regions, ImageCol, ImageRow : Histo2Dim : : )。 输入参数&#xff…

(vue)el-table在表头添加筛选功能

(vue)el-table在表头添加筛选功能 筛选前&#xff1a; 选择条件&#xff1a; 筛选后&#xff1a; 返回数据格式: 代码: <el-tableref"filterTable":data"projectData.list"height"540":header-cell-style"{border-bottom: 1px soli…

使用 Marp 将 Markdown 导出为 PPT 后不可编辑的原因说明及解决方案

Marp 是一个流行的 Markdown 演示文稿工具&#xff0c;能够将 Markdown 文件转换为 PPTX 格式。然而&#xff0c;用户在使用 Marp 导出 PPT 时&#xff0c;可能会遇到以下问题&#xff1a; 导出 PPT 不可直接编辑的原因 根据 Marp GitHub 讨论&#xff0c;Marp 导出的 PPTX 文…

UE5安装Fab插件

今天才知道原来Fab也有类似Quixel Bridge的插件&#xff0c;于是立马就安装上了&#xff0c;这里分享一下安装方法 在Epic客户端 - 库 - Fab Library 搜索 Fab 即可安装Fab插件 然后重启引擎&#xff0c;在插件面板勾选即可 然后在窗口这就有了 引擎左下角也会多出一个Fab图标…

Gin- Cookie\Session相关

Cookie&#xff0c;Session是什么&#xff1f; Cookie直译小饼干&#xff0c;是一些数据信息&#xff0c;类似于小型文本文件&#xff0c;存储在浏览器上。Cookie是进行第一次登录之后&#xff0c;由服务器创建后返回给浏览器的。之后&#xff0c;每当浏览器再次向同一服务器发…

使用Python打造高效的PDF文件管理应用(合并以及分割)

在日常工作和学习中&#xff0c;我们经常需要处理大量PDF文件。手动合并、分割PDF不仅耗时&#xff0c;还容易出错。今天&#xff0c;我们将使用Python的wxPython和PyMuPDF库&#xff0c;开发一个强大且易用的PDF文件管理工具。 C:\pythoncode\new\mergeAndsplitPdf.py 所有代…

深度学习中自适应学习率调度器

传统观点认为&#xff0c;太大的学习率不利于优化深度神经网络&#xff0c;而相比固定的学习率而言&#xff0c;变化的学习率更能提供快速的收敛。基于此&#xff0c;本文作者基于理论基础提出了一个计算深度神经网络学习率的新方法。实验结果证明了该方法的有效性。 训练神经…

文献研读|基于像素语义层面图像重建的AI生成图像检测

前言&#xff1a;本篇文章主要对基于重建的AI生成图像检测的四篇相关工作进行介绍&#xff0c;分别为基于像素层面重建的检测方法 DIRE 和 Aeroblade&#xff0c;以及基于语义层面重建的检测方法 SimGIR 和 Zerofake&#xff1b;并对相应方法进行比较。 相关文章&#xff1a;论…

ElasticSearch06-分片节点分配

零、文章目录 ElasticSearch06-分片节点分配 1、单节点多分片多副本 &#xff08;1&#xff09;启动一个空节点 节点的配置如下 cluster.name: mycluster node.name: node-01 node.master: true node.data: true network.host: 127.0.0.1 http.port: 9201 transport.tcp.p…

信息学奥赛一本通 1438:灯泡 | 洛谷 P5931 [清华集训2015] 灯泡

【题目链接】 ybt 1438&#xff1a;灯泡 洛谷 P5931 [清华集训2015] 灯泡 【题目考点】 1. 三分 求函数极值 2. 相似三角形 3. 对钩函数 【解题思路】 首先考虑影子还没有到达对面墙壁的情况 记BM长度为x&#xff0c;影子为AM&#xff0c;长度为L。三角形ABC相似于三角…

揭开 Choerodon UI 拖拽功能的神秘面纱

01 引言 系统的交互方式主要由点击、选择等组成。为了提升 HZERO 系统的用户体验、减少部分操作步骤&#xff0c;组件库集成了卓越的拖拽功能&#xff0c;让用户可以更高效流畅的操作系统。 例如&#xff1a;表格支持多行拖拽排序、跨表数据调整、个性化调整列顺序&#xff1…

【物联网技术与应用】实验4:继电器实验

实验4 继电器实验 【实验介绍】 继电器是一种用于响应施加的输入信号而在两个或多个点或设备之间提供连接的设备。换句话说&#xff0c;继电器提供了控制器和设备之间的隔离&#xff0c;因为设备可以在AC和DC上工作。但是&#xff0c;他们从微控制器接收信号&#xff0c;因此…

fpga系列 HDL:Quartus II 时序约束 静态时序分析 (STA) test.out.sdc的文件结构

test.out.sdc的文件结构 ## Generated SDC file "test.out.sdc"## Copyright (C) 1991-2013 Altera Corporation ## Your use of Altera Corporations design tools, logic functions ## and other software and tools, and its AMPP partner logic ## functions,…

Windows安全中心(病毒和威胁防护)的注册

文章目录 Windows安全中心&#xff08;病毒和威胁防护&#xff09;的注册1. 简介2. WSC注册初探3. WSC注册原理分析4. 关于AMPPL5. 参考 Windows安全中心&#xff08;病毒和威胁防护&#xff09;的注册 本文我们来分析一下Windows安全中心&#xff08;Windows Security Center…

HTML中的Vue3解析!

#Vue 3 是一个用于构建用户界面的渐进式 JavaScript 框架。它在 HTML 中发挥着重要的作用&#xff0c;可以让开发者轻松地创建交互式的网页应用。与 HTML 结合时&#xff0c;Vue 3 通过自定义指令、组件等方式增强了 HTML 的功能。# 一、vue的概述 Vue 采用了双向数据绑定机制…

ARM嵌入式学习--第八天(PWM)

PWM -PWM介绍 PWM&#xff08;pulse Width Modulation&#xff09;简称脉宽调制&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术&#xff0c;广泛应用在测量&#xff0c;通信&#xff0c;工控等方面 PWM的频率 是指在1秒钟内&#xff0c;信号从…

TongESB7.1.0.0安装参考指引+测试参考(by lqw)

文章目录 安装安装准备配置jdk安装管理中心&#xff08;manager&#xff09;安装运行时(server)安装mysql并配置manager&#xff08;新装阶段考虑&#xff09;放入授权启动内置redis启动内置redis启动manager和server停止manager和server访问控制台如何在控制台上重置密码 测试…