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,

  2.                   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[20];

  14.     char sex;

  15. };

  16.  

  17. int main(int argc,char *argv[]) //这个进程用于创建映射区进行写。

  18. {

  19.     if(argc != 2)

  20.     {

  21.         printf("./a,out  file");

  22.         exit(1);

  23.     }

  24.  

  25.     struct STU student = {10,"xiaoming",'m'};

  26.  

  27.     int fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0644);

  28.     if(fd < 0)

  29.     {

  30.         perror("open");

  31.         exit(2);

  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,0);//创建一个结构体大小的共享映射区。共享映射区我们可以当做数组区看待。

  36.     if(p == MAP_FAILED)

  37.     {

  38.         perror("mmap");

  39.         exit(3);

  40.     }

  41.     close(fd); //关闭不用的文件描述符。

  42.     while(1)

  43.     {

  44.         memcpy(p,&student,sizeof(student));

  45.         student.age++;

  46.         sleep(1);

  47.     }

  48.     int ret = munmap(p,sizeof(student));

  49.     if(ret < 0)

  50.     {

  51.         perror("mmumap");

  52.         exit(4);

  53.     }

  54.  

  55.     return 0;

  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[20];

  13.     char sex;

  14. };

  15.  

  16. int main(int argc,char *argv[]) //这个进程读

  17. {

  18.     if(argc != 2)

  19.     {

  20.         printf("./a,out  file");

  21.         exit(1);

  22.     }

  23.  

  24.  

  25.     int fd = open(argv[1],O_RDONLY,0644);

  26.     if(fd < 0)

  27.     {

  28.         perror("open");

  29.         exit(2);

  30.     }

  31.     

  32.     struct STU student;

  33.  

  34.     struct STU *p = (struct STU*)mmap(NULL,sizeof(struct STU),PROT_READ,MAP_SHARED,fd,0);

  35.     if(p == MAP_FAILED)

  36.     {

  37.         perror("mmap");

  38.         exit(3);

  39.     }

  40.     close(fd);

  41.     int i = 0;

  42.     while(1)

  43.     {

  44.         

  45.         printf("id = %d\tname = %s\t%c\n",p->age,p->name,p->sex);    

  46.         sleep(2);

  47.     }

  48.     int ret = munmap(p,sizeof(student));

  49.     if(ret < 0)

  50.     {

  51.         perror("mmumap");

  52.         exit(4);

  53.     }

  54.  

  55.     return 0;

  56. }

代码截图:


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

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. shm 共享内存 android,C++下shm共享内存模块

    共享内存(这是IPC最快捷的方式) 是什么 我的第一个服务器项目分了前后端,而其中前后端的数据通讯就是使用shm共享内存的方式,所以对于这块会比较有感觉. 1.共享内存是在多个进程之间共享内存区域的一 ...

  3. mmap内存映射、system V共享内存和Posix共享内存

    linux内核支持多种共享内存方式,如mmap内存映射,Posix共享内存,以system V共享内存.当内核空间和用户空间存在大量数据交互时,共享内存映射就成了这种情况下的不二选择.它能够最大限度的 ...

  4. linux mmap实例_Linux下通过共享内存和mmap实现进程间通讯(含实例)

    前言 最近在学习GNU/Linux内核,看到mmap的时候书上说: mmap/munmap接口函数是用户最常用的两个系统调用接口,无论是在用户程序中分配内存.读写大文件.链接动态库文件,还是多进程间共 ...

  5. Linux学习之系统编程篇:shm 共享内存及其操作函数

    一.shm 和 mmap 的区别 (1)mmap 是在磁盘上建立一个文件,每个进程地址空间中开辟出一块空间进行映射.shm 每个进程最终会映射到同一块物理内存.shm 保存在物理内存,这样读写的速度最 ...

  6. linux管道和共享内存的区别,linux 管道、消息队列、共享内存的对比

    ------管道 管道的优点是不需要加锁,缺点是默认缓冲区太小,只有4K,同时只适合父子进程间通信,而且一个管道只适合单向通信,如果要双向通信需要建立两个.而且不适合多个子进程,因为消息会乱,它的发送 ...

  7. [转]Linux 进程间通信:共享内存

    (上) 级别: 初级 郑彦兴 (mlinux@163.com), 国防科大攻读博士学位 2003 年 5 月 01 日 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B ...

  8. Linux访问其他进程空间,Linux环境进程间通信系列(五):共享内存

    共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A . B 共享内存的意思是,同一块物理内存被映射到进程 A . B 各自的进程地址空间.进程 A 可以即时看到进程 B ...

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

    共享内存(上) 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存 ...

最新文章

  1. OpenCV中使用YOLO对象检测
  2. 币知识——比特币现金
  3. Py之Matplotlib:python包之Matplotlib库图表绘制经验总结(中英文字体修改、横坐标文字进行横/纵向显示、控制坐标轴范围等)之详细攻略
  4. 在idea中把项目上传到GitHub库中
  5. mysql 基于时间分区_MySQL基于时间字段进行分区的方案总结
  6. 58到家为2000万家庭提供上门生活服务的背后是云计算的高效支撑
  7. Linux系统编程1:基础篇之Linux中使用率最高的一些命令
  8. 2018.11.04 洛谷P1081 开车旅行(倍增)
  9. 与 Netcraft 携手为 GlobalSign 的客户提供先进的保护措施以防止网站遭受恶意入侵和钓鱼攻击...
  10. 操作系统原理好书推荐
  11. 华为、小米、OPPO三大厂商字体对比 这款更加舒适易读
  12. Cocos Creator 3D 摇杆控制器一种简单实现!
  13. 版权符号--如何在页面完美显示版权符号,版权符号字体
  14. 树莓派智能小车资料整理
  15. 【图论】图的最短路径问题——有权图的单源最短路(Dijkstra算法)
  16. opencv 涂抹区域得方法
  17. Layui的基本使用(前端登录操作步骤)
  18. 聚合型代码审计工具QingScan使用实践
  19. Conflux TokenGazer AMA活动内容回顾
  20. 微软巨资收购Skype 网络电话行业受关注

热门文章

  1. redis基本类型以及优点特性
  2. 数据结构(6) -- 查找
  3. poj 2492 A Bug's Life
  4. jQuery的DOM操作之取值/赋值(1)
  5. 为什么TCP连接至少3次握手
  6. 数据结构题:根据所给权值设计相应的哈夫曼树,并设计哈夫曼编码
  7. linux 进程通信比较,浅析Linux进程通信的几种方式及其比较
  8. 解决 FtpClient 类无法导入 .
  9. 25个优秀的Ajax技术和实例
  10. load styles.php,wordpress后台管理超时没反应:load-scripts.php载入缓慢出错