进程间通信学习笔记(共享内存)

内存映射概念:

  • 共享内存可以通过mmap()映射普通文件
  • 使一个磁盘文件与内存中的一个缓冲区相映射,进程可以像访问普通文件一样对文件进行访问,不必再强调read,write。

mmap的优点:

  • 实现了用户空间和内核空间的高效交互方式

 

mmap的示例:

 函数定义:

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

功能:创建共享内存映射

函数返回值:成功返回创建的映射区首地址,失败返回MAP_FAILED(((void*)-1)),设置errno值


参数说明

addr:指定要映射的内存地址,一般设置为NULL让操作系统自动选择合适的内存地址。

length:必须>0,映射地址空间的字节数,它从被映射文件开头offset个字节开始算起。

prot:指定共享内存的访问权限。可取如下几个值的可选:PROT_READ(可读),PROT_WRITE(可写),PROT_EXEC(可执行),PROT_NONE(不可访问)。

flags:由以下几个常值指定:MAP_SHARED(共享的)MAP_PRIVATE(私有的)MAP_FIXED(表示必须使用start参数作为开始地址,如果失败不进行修正),其中MAP_SHARED和MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用,MAP_ANONYMOUS(匿名映射,用于血缘关系进程间通信)

fd:表示要映射的文件句柄。如果匿名映射写-1。

offset:表示映射文件的偏移量,一般设置为0表示从文件头部开始映射。


注意事项

(1)创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区。

(2)当MAP_SHARED时,要求:映射区的权限应<=文件打开的权限(出于对映射区的保护),如果不满足报非法参数(Invalid argument)错误。

(3)映射区的释放与文件关闭无关,只要映射建立成功,文件可以立即关闭。

(4)用于映射的文件大小必须>0,当映射文件为0时,指定非0大小创建映射区,访问映射地址会报总线错误,指定0大小创建映射区,报非法参数错误(Invalid argument)

(5)文件偏移量必须为0或者4K的整数倍(不是会报非法参数(Invalid argument)错误)。

(6)映射大小可以大于文件大小,但只能访问文件page的内存地址,否则报总线错误,超出映射的内存大小报段错误。


(6)的解释:

假如文件大小为37字节,即文件test为37字节大小,通过mmap申请2K内存,系统是可以访问3K的内存的,因为文件小于4K的话一次最少分配4K内存,如果访问5K的(报段错误)。但是如果申请6K内存,则5K的内存不能访问(报总线错误),因为系统会根据test文件的大小分配内存,此时也是只会分配4K。

示例代码:

#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{void *addr;int fd;fd = open("test",O_RDWR);if (fd < 0){perror("open");return 0;}addr = mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if (addr == MAP_FAILED){perror("mmap");return 0;}// memcpy(addr,"abcdefg",7);printf("read=%s\n",(char*)addr);
}

将文件test进行映射,修改test内容,就会映射文件内容

两个进程通过共享内存进行通信:

mmap_w.c

#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{void *addr;int fd;fd = open("test",O_RDWR);if (fd < 0){perror("open");return 0;}addr = mmap(NULL,2048,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if (addr == MAP_FAILED){perror("mmap");return 0;}close(fd);int i = 0;while (i < 2048){memcpy((addr+i),"a",1);i++;sleep(1);}return 0;// memcpy(addr,"abcdefg",7);// printf("read=%s\n",(char*)addr);
}

mmap_r.c

#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{void *addr;int fd;fd = open("test",O_RDWR);if (fd < 0){perror("open");return 0;}addr = mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if (addr == MAP_FAILED){perror("mmap");return 0;}while (1){printf("read=%s\n",(char*)addr);sleep(1);}return 0;// memcpy(addr,"abcdefg",7);}

向test文件映射的共享内存,一秒写一个a,然后一秒读一次

匿名映射mmap_n.c

#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>#include <fcntl.h>int main()
{void *addr;addr = mmap(NULL,2048,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);if (addr == MAP_FAILED){perror("mmap");return 0;}pid_t pid;pid = fork();if (pid < 0){perror("fork");}else if (pid > 0){memcpy(addr,"1234567890",10);wait(NULL);//回收子进程}else{sleep(1);printf("read father val= %s\n",(char *)addr);}//释放共享内存munmap(addr,2048);return 0;// memcpy(addr,"abcdefg",7);// printf("read=%s\n",(char*)addr);
}

运行结果:

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

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

相关文章

开源大模型LLM大爆发,数据竞赛已开启!如何使用FuseLLM实现大语言模型的知识融合?

开源大模型LLM大爆发&#xff0c;数据竞赛已开启&#xff01;如何使用FuseLLM实现大语言模型的知识融合&#xff1f; 现在大多数人都知道LLM是什么&#xff0c;以及可以做什么。 人们讨论着它的优缺点&#xff0c;畅想着它的未来&#xff0c; 向往着真正的AGI&#xff0c;又有…

unity初学问题:如何修改图片的坐标

如图&#xff0c;我们想要修改图片的轴心点坐标&#xff08;Pivot&#xff09; 选择图片组 打开编辑器在里面修改即可&#xff08;最下面的Custom Pivot&#xff09;

C++之atexit-pthread用法详解

目录 1.atexit()函数使用说明 pthread_once() 函数详解 1.atexit()函数使用说明 NAME atexit - 用来注册执行 exit()函数前执行的终止处理程序.SYNOPSIS #include <stdlib.h> int atexit(void (*function)(void))&#xff1b;DESCRIPTION atexit()用来注册终止处理程序&…

51单片机(6)-----直流电机的介绍与使用(通过独立按键控制电机的运行)

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 目录 一. 直流电机模块介绍 1.直流电机介绍 2.电机参数 二. 程序设计…

算法C++

枚举 1.化段为点 前缀和 eg:给一个数列&#xff0c;算x到y个数的和 #include <iostream> #include <vector> using namespace std;int main() {int n;cin>>n;vector<int> a(n);vector<int> sum(n1,0);for(int i0;i<n;i){scanf…

深入探究【观察者模式】:简单音乐会售票系统案例分析

文章目录 1.观察者模式概述基本概念&#xff1a;工作原理&#xff1a; 2.案例-音乐会抢票2.1.具体实现2.1.1.被观察者接口2.1.2.被观察者实现类2.1.3.定义观察者接口2.1.3.定义观察者实现类2.1.4.测试观察者 3.总结3.1.优点和局限性3.2.思考 1.观察者模式概述 观察者模式是一种…

网站三合一缩略图片介绍展示源码

网站三合一缩略图片介绍展示源码&#xff0c;PHP源码&#xff0c;运行需要php环境支持&#xff0c;效果截图如下 蓝奏云下载&#xff1a;https://wfr.lanzout.com/ihY8y1pgim6j

swagger-ui.html报错404,解决办法

swagger-ui.html报错404,解决办法&#xff01;现在后端开发项目中&#xff0c;为了节省时间&#xff0c;使用swagger插件&#xff0c;可以方便的快捷生成接口文档。但是如果你在请求前端页面路径比如&#xff1a;http://127.0.0.1:7777/swagger-ui.html。找不到。那是因为你的配…

部分卷积与FasterNet模型详解

简介 论文原址&#xff1a;2023CVPR&#xff1a;https://arxiv.org/pdf/2303.03667.pdf 代码仓库&#xff1a;GitHub - JierunChen/FasterNet: [CVPR 2023] Code for PConv and FasterNet 为了设计快速神经网络&#xff0c;很多工作都集中于减少浮点运算&#xff08;FLOPs&a…

【蓝桥杯】快读|min和max值的设置|小明和完美序列|​顺子日期​|星期计算|山

目录 一、输入的三种方式 1.最常见的Scanner的输入方法 2.数据多的时候常用BufferedReader快读 3.较麻烦的StreamTokenizer快读&#xff08;用的不多&#xff09; StreamTokenizer常见错误&#xff1a; 二、min和max值的设置 三、妮妮的翻转游戏 四、小明和完美序列 五…

flink学习之旅(二)

目前flink中的资源管理主要是使用的hadoop圈里的yarn&#xff0c;故此需要先搭建hadoop环境并启动yarn和hdfs&#xff0c;由于看到的教程都是集群版&#xff0c;现实是只有1台机器&#xff0c;故此都是使用这台机器安装。 1.下载对应hadoop安装包 https://dlcdn.apache.org/h…

3D图像与表格的结合MICCAI2021

先前从大脑MRI诊断阿尔茨海默病的工作表明&#xff0c;卷积神经网络&#xff08;CNNs&#xff09;可以利用图像信息进行分类。然而&#xff0c;很少有研究关注这些模型如何利用表格信息&#xff0c;如患者统计数据或实验测量数据。这里介绍了动态仿射特征图变换&#xff08;DAF…