【转载】原文链接:https://blog.csdn.net/hj605635529/article/details/73163513

linux中的两种共享内存。一种是我们的IPC通信System V版本的共享内存,另外的一种就是我们今天提到的存储映射I/O(mmap函数)

在说mmap之前我们先说一下普通的读写文件的原理,进程调用read或是write后会陷入内核,因为这两个函数都是系统调用,进入系统调用后,内核开始读写文件,假设内核在读取文件,内核首先把文件读入自己的内核空间,读完之后进程在内核回归用户态,内核把读入内核内存的数据再copy进入进程的用户态内存空间。实际上我们同一份文件内容相当于读了两次,先读入内核空间,再从内核空间读入用户空间。

 Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改,mmap()系统调用使得进程之间可以通过映射一个普通的文件实现共享内存。普通文件映射到进程地址空间后,进程可以向访问内存的方式对文件进行访问,不需要其他系统调用(read,write)去操作。

mmap图示例:

mmap系统调用介绍

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

这就是mmap系统调用的接口,mmap函数成功返回指向内存区域的指针,图上的进程的地址空间的开始地址就是mmap函数的返回值,失败返回MAP_FAILED。

addr,某个特定的地址作为起始地址,当被设置为NULL,系统会在地址空间选择一块合适的内存区域。

length说的是内存段的长度。

prot是用来设定内存段的访问权限。

prot参数 说明
PROT_READ 内存段可读
PROT_WRITE 内存段可写
PROT_EXEC 内存段可执行
PROT_NONE 内存段不能被访问

flags参数控制内存段内容被修改以后程序的行为。

flags参数 说明
MAP_SHARED 进程间共享内存,对该内存段修改反映到映射文件中。提供了POSIX共享内存
MAP_PRIVATE 内存段为调用进程所私有。对该内存段的修改不会反映到映射文件
MAP_ANNOYMOUS 这段内存不是从文件映射而来的。内容被初始化为全0
MAP_FIXED 内存段必须位于start参数指定的地址处,start必须是页大小的整数倍(4K整数倍)
MAP_HUGETLB 按照大内存页面来分配内存空间

fd参数是用来被映射文件对应的文件描述符。通过open系统调用得到。offset设定从何处进行映射。

mmap使用注意事项:

利用mmap进行非血缘进程间通信代码:

 
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. #include<fcntl.h>
  5. #include<sys/types.h>
  6. #include<sys/stat.h>
  7. #include<sys/mman.h>
  8. #include<string.h>
  9.  
  10. struct STU
  11. {
  12. int age;
  13. char name[];
  14. char sex;
  15. };
  16.  
  17. int main(int argc,char *argv[]) //这个进程用于创建映射区进行写。
  18. {
  19. if(argc != )
  20. {
  21. printf("./a,out file");
  22. exit();
  23. }
  24.  
  25. struct STU student = {,"xiaoming",'m'};
  26.  
  27. int fd = open(argv[],O_RDWR|O_CREAT|O_TRUNC,);
  28. if(fd < )
  29. {
  30. perror("open");
  31. exit();
  32. }
  33. ftruncate(fd,sizeof(struct STU)); //文件拓展大小。
  34.  
  35. struct STU *p = (struct STU*)mmap(NULL,sizeof(struct STU),PROT_READ|PROT_WRITE,MAP_SHARED,fd,);//创建一个结构体大小的共享映射区。共享映射区我们可以当做数组区看待。
  36. if(p == MAP_FAILED)
  37. {
  38. perror("mmap");
  39. exit();
  40. }
  41. close(fd); //关闭不用的文件描述符。
  42. while()
  43. {
  44. memcpy(p,&student,sizeof(student));
  45. student.age++;
  46. sleep();
  47. }
  48. int ret = munmap(p,sizeof(student));
  49. if(ret < )
  50. {
  51. perror("mmumap");
  52. exit();
  53. }
  54.  
  55. return ;
  56. }
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. #include<fcntl.h>
  5. #include<sys/types.h>
  6. #include<sys/stat.h>
  7. #include<sys/mman.h>
  8.  
  9. struct STU
  10. {
  11. int age;
  12. char name[];
  13. char sex;
  14. };
  15.  
  16. int main(int argc,char *argv[]) //这个进程读
  17. {
  18. if(argc != )
  19. {
  20. printf("./a,out file");
  21. exit();
  22. }
  23.  
  24. int fd = open(argv[],O_RDONLY,);
  25. if(fd < )
  26. {
  27. perror("open");
  28. exit();
  29. }
  30.  
  31. struct STU student;
  32.  
  33. struct STU *p = (struct STU*)mmap(NULL,sizeof(struct STU),PROT_READ,MAP_SHARED,fd,);
  34. if(p == MAP_FAILED)
  35. {
  36. perror("mmap");
  37. exit();
  38. }
  39. close(fd);
  40. int i = ;
  41. while()
  42. {
  43.  
  44. printf("id = %d\tname = %s\t%c\n",p->age,p->name,p->sex);
  45. sleep();
  46. }
  47. int ret = munmap(p,sizeof(student));
  48. if(ret < )
  49. {
  50. perror("mmumap");
  51. exit();
  52. }
  53.  
  54. return ;
  55. }

代码截图:



分析:因为只创建一个结构体大小的共享内存,后面写入的数据把前面写入的数据覆盖了。

shm调用介绍:参见上一篇博客

http://blog.csdn.net/hj605635529/article/details/67636526
 
shm图示例:
 
 

(1)通过int shmget(key_t key, size_t size, int shmflg);在物理内存创建一个共享内存,返回共享内存的编号。
(2)通过void *shmat(int shmid, constvoid shmaddr,int shmflg);连接成功后把共享内存区对象映射到调用进程的地址空间
(3)通过void *shmdt(constvoid* shmaddr);断开用户级页表到共享内存的那根箭头。
(4)通过int shmctl(int shmid, int cmd, struct shmid_ds* buf);释放物理内存中的那块共享内存。

 
 
 

总结mmap和shm:
1、mmap是在磁盘上建立一个文件,每个进程地址空间中开辟出一块空间进行映射。
而对于shm而言,shm每个进程最终会映射到同一块物理内存。shm保存在物理内存,这样读写的速度要比磁盘要快,但是存储量不是特别大。
2、相对于shm来说,mmap更加简单,调用更加方便,所以这也是大家都喜欢用的原因。
3、另外mmap有一个好处是当机器重启,因为mmap把文件保存在磁盘上,这个文件还保存了操作系统同步的映像,所以mmap不会丢失,但是shmget就会丢失。

 

mmap映射区和shm共享内存的区别总结的更多相关文章

  1. mmap和shm共享内存的区别和联系

    共享内存的创建 根据理论: 1. 共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制.共享内存可以通过mmap()映射普通文件(特殊情况下还可以采用匿 ...

  2. (转)mmap和shm共享内存的区别和联系

    共享内存的创建 根据理论: 1. 共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制.共享内存可以通过mmap()映射普通文件 (特殊情况下还可以采用 ...

  3. 【VS开发】内存映射文件进程间共享内存

    内存映射文件进程间共享内存 内存映射文件的另一个功能是在进程间共享数据,它提供了不同进程共享内存的一个有效且简单的方法.后面的许多例子都要用到共享内存.共享内存主要是通过映射机制实现的.Windows ...

  4. POSIX systemV共享内存的区别

    POISX共享内存分为两种方式: 1.内存映射文件 特点:共享内存的改变能在文件中体现: 2.共享内存区对象 特点:共享内存的改变在文件上看不出来(实际上根本打不开该文件): 以上两者都是基于mmap ...

  5. Linux环境编程之共享内存区(一):共享内存区简单介绍

    共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...

  6. 使用mmap可以方便地添加共享内存

    使用mmap添加的共享内存. 局限: 只能在有亲属关系的进程之间使用. #include <stdio.h> #include <stdlib.h> #include < ...

  7. SAP内存、ABAP内存、共享内存的 区别

    区别: (1)SAP内存使用 SET/GET parameters 方法: SET  PARAMETER  ID  ‘MAT’ field P_MATNR. GET  PARAMETER  ID  ‘ ...

  8. 共享内存与存储映射(mmap)

    [前言]对这两个理解还是不够深刻,写一篇博客来记录一下. 首先关于共享内存的链接:共享内存.里面包含了创建共享内存区域的函数,以及两个进程怎么挂载共享内存通信,分离.释放共享内存. 共享内存的好处就是 ...

  9. Linux环境进程间通信(五): 共享内存(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

随机推荐

  1. day40-python多进程多线程-多线程实例和锁

    多线程 线程是应用程序中工作的最小单元. 多线程是现实有两种方式:方法一:将要执行的方法作为参数传给Thread的构造方法(和多进程类似)t = threading.Thread(target=act ...

  2. Jsp 国际化访问首页选择展示不同字体小例子

    要求:创建一个首页,默然显示英文信息,但可以让用户选择使用英文,繁体中文或简体中文. 1.编写hello_en_US.txt,内容如下: cc.openhome.welcome=welcomecc.o ...

  3. Linux之expr命令详解

    expr命令: expr命令是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串. –格式为: expr Expression(命令读入Expressi ...

  4. slick插件一些配置

  5. 外网如何访问web项目holer实现篇

    外网访问WEB 内网主机上安装了WEB服务器,只能在局域网内访问,怎样从公网也能访问本地WEB应用? 本文将介绍使用holer实现的具体步骤. 1. 准备工作 1.1 安装Java 1.7及以上版本 ...

  6. wpf UI 元素类型

  7. python day19--面向对象,接口,封装

    #1.接口类,对象类.规范类中方法的统一. # 第一版:三个类,每个类中有相同的方法 # class Alipay: # def __init__(self,money): # self.money= ...

  8. windows常用命令积累

    命令行可以对文件进行操作,copy 路径\文件名 路径\文件名,复制文件:move 路径\文件名 路径\文件名,移动文件:del 文件名,删除文件. cd与dir命令,dir命令显示当前目录下的文件及 ...

  9. Erlang-接口技术

    系统的构建一定会设计到简历接口,让他与不同的语言的应用程序之间简历系统的联系.这就叫做erlang的接口技术. 接口技术的三种实现方法: 1.让程序以外部操作系统进行的形式在Erlang虚拟机以外运行 ...

  10. python -django 之第三方支付

    神魔是第三方支付: 第三方支付是指具有一定实力和信誉保障的第三方独立机构.通过与各大银行签订合同,建立连接用户和银行支付结算系统的平台,从而实现电子支付模式.从另一个角度来看,第三方支付就是非金融机构 ...