LINUX学习笔记

  • mmap 进程通信
    • 1. mmap 函数声明及头文件包含
      • 1.1 参数说明
      • 1.2 mmap 通信demo
    • 2. mmap 注意事项:
      • 2.1 mmap 函数的保险使用方法:
    • 3. demo 父子进程间mmap通信
    • 4. demo 非血缘关系进程间mmap通信
    • 5. mmap通信与fifo和文件通信的差异
    • 6. 匿名映射(只能用于血缘关系进程间通信)

mmap 进程通信

1. mmap 函数声明及头文件包含

man 2 mmap#include<sys/mman.h>
/* 创建映射区 */
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
/* 释放映射区 */
int munmap(void *addr, size_t length);

1.1 参数说明

参数:

  • addr:指定映射区的首地址。通常传NULL,表示让系统自动分配
  • length:共享映射区的大小(<= 文件实际大小)
  • prot:共享内存区的读写属性
         PROT_READ
         PROT_WRITE
         PROT_READ | PROT_WRITE
  • flag:标注共享内存的共享属性
         MAP_SHARED(对内存的修改会反映到磁盘上)
         MAP_PRIVATE(对内存的修改不会反映到磁盘上)
  • fd:用于创建共享内存映射区的那个文件的 文件描述符
  • offset:从文件偏移位置开始建立映射区 (必须是4k的整数倍4096)默认0,表示映射文件全部

mmap返回值:

  • 成功—映射区的首地址
  • 失败—MAP_FAILED( 实质(void*)-1 ),设置errno
    !!!!!mmap 极易容易出错,切记一定要检查mmap的返回值!!!!!!

munmap返回值:

  • 成功— 0
  • 失败— -1,设置errno

1.2 mmap 通信demo

  1. open 创建一个文件,并用 lseek 或者 ftruncate 拓展文件大小
  2. mmap创建映射区
  3. 往映射区写
  4. 读映射区
  5. 释放映射区
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<sys/mman.h>
#include<fcntl.h>void sys_error(const char * str)
{perror(str);exit(1);
}int main(int argc, char * argv [])
{int fd, ret;char* p = NULL;fd = open("testmap", O_RDWR | O_CREAT | O_TRUNC, 0644);if (fd < 0){sys_error("open error\n");}/*lseek(fd, 10 , SEEK_END);  // 与 ftruncate 等效write(fd, "\0", 1);*/ftruncate(fd, 10);          // 需要写权限才能拓展文件大小int len = lseek(fd, 0, SEEK_END);p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED)   // 返回值一定要检查{sys_error("mmap error\n");}strcpy(p, "hello mmap");printf("------%s\n, p");ret = munmap(p, len);if (ret == -1)sys_error("munmap error\n");close(fd);return 0;}

有一个创建的 testmap 文件!并实现内存映射

2. mmap 注意事项:

  1. 用于创建映射区的文件大小为0,实际指定非0大小创建映射区,出“总线错误”
  2. 用于创建映射区的文件大小为0,实际制定0大小创建映射区,出“无效参数”
  3. 用于创建映射区的文件读写属性为 只读。映射区属性为 读|写, 出“无效参数”
  4. 创建映射区,需要read权限。(创建映射区的过程中,隐含着一次对映射文件的读操作)当访问权限指定为 MAP_SHARED 时mmap的读写权限,应该 <= 文件open权限。 只写不行
  5. 文件描述符fd,在mmap创建映射区完成即可关闭。后续访问文件,用 地址 访问
  6. offset必须是4096的整数倍。(MMU 映射的最小单位是 4k)
  7. 对申请的映射区内存,不能越界访问
  8. munmap 用于释放的地址,必须是mmap申请返回的地址,对申请的映射区地址做操作赋值之前应该备份一份地址用作munmap
  9. 映射区访问权限为“私有”MAP_PRIVATE,对内存所做的所有修改,只在内存有效,不会反映到物理磁盘上。
  10. 映射区访问权限为“私有”MAP_PRIVATE,只需要open文件有读权限,就可用于创建映射区。因为私有不反应到物理磁盘上面,没有写的过程

2.1 mmap 函数的保险使用方法:

1. fd = open("文件名", O_RDWR)
2. p = mmap(NULL,有效文件大小, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
3. close(fd)
4. munmap(p, length)

3. demo 父子进程间mmap通信

父子等有血缘关系的进程之间也可以通过 mmap 建立的映射区来完成数据通信。但相应的要在创建映射区的时候指定对应的标志位参数 flags:

  • MAP_SHARED(共享映射): 父子进程共享映射区
  • MAP_PRIVATE(私有映射):父子进程各自独占映射区(各自读各自的)
  1. open创建文件,ftruncate 拓展文件大小
  2. mmap 建立映射区
  3. close 关闭文件
  4. fork 创建子进程
  5. 对映射区进程写读操作(写读操作有先后顺序 靠sleep实现)
  6. 回收映射区
/* mmap_fork.c */
#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;int fd;pid_t pid;fd = open("temp", O_RDWR | O_CREAT | O_TRUNC, 0644);if (fd < 0){perror("open error\n");exit(1);}ftruncate(fd, 4);p = (int*)mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED){perror("mmap error\n");exit(1);}close(fd);pid = fork();if (pid == 0){*p = 7000;   // 对映射区空间进行写操作var = 1000;printf("child, *p = %d, var = %d\n", *p, var);}else if(pid >0){sleep(1);printf("parent, *p = %d, var = %d\n", *p, var);wait(NULL);int ret = munmap(p,4);if (ret == -1){perror("munmap error\n");exit(1);}}return 0;
}

4. demo 非血缘关系进程间mmap通信

memcpy 函数:

memcpy --copy memory area------------
#include<string.h>void* memcpy(void* dest, void* src, size_t n);
---------------

写进程

  1. open创建文件,ftruncate 拓展文件大小
  2. mmap 创建映射区
  3. close关闭文件
  4. 往映射区内进行写操作
  5. 回收映射区
/* mmap_w.c */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/mman.h>void sys_error(const char * str)
{perror(str);exit(1);
}struct student{int id;char name[256];int age;
};int main(int argc, char * argv [ ])
{struct student stu = {0, "xiaoming", 18};struct student* p;int fd;fd = open("mmap_test", O_RDWR | O_CREAT |O_TRUNC, 0664);if (fd == -1)sys_error("open error\n");ftruncate(fd, sizeof(stu));p = (struct student*)mmap(NULL, sizeof(stu), PROT_READ |PROT_WRITE, MAP_SHARED, fd, 0);if (p == MAP_FAILED)sys_error("mmap error\n");close(fd);while(1){memcpy(p, &stu, sizeof(stu));stu.id++;sleep(1);}int ret = munmap(p, sizeof(stu));if (ret == -1){sys_error("munmap error\n");}return 0;}

读进程

  1. open打开写进程创建的文件
  2. mmap 建立映射区
  3. close关文件
  4. 读映射区内容
  5. 回收映射区
/* mmap_r.c */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/mman.h>void sys_error(const char * str)
{perror(str);exit(1);
}struct student{int id;char name[256];int age;
};int main(int argc, char * argv [])
{struct student stu;struct student* p;int fd;fd = open("mmap_test", O_RDONLY);if (fd == -1)sys_error("open error\n");p = (struct student*)mmap(NULL, sizeof(stu), PROT_READ , MAP_SHARED, fd, 0);if (p == MAP_FAILED)sys_error("mmap error\n");close(fd);while(1){printf("id = %d, name = %s, age = %d\n",p->id,p->name, p->age);sleep(1);}int ret = munmap(p, sizeof(stu));if (ret == -1){sys_error("munmap error\n");}}

编译、运行:

5. mmap通信与fifo和文件通信的差异

mmap 同 fifo 区别:

  • mmap:数据可以反复读取
  • fifo:数据只能一次读取

mmap 同 文件 区别:

  • mmap:映射到内存上,可以直接对内容进行指针操作
  • 文件:open、close 打开关闭文件,read、write 来实现文件通信

6. 匿名映射(只能用于血缘关系进程间通信)

通常为了创建映射区要 open 一个 temp 文件,创建好了在 close 掉,比较麻烦。在父子进程通信中,可以直接使用匿名映射来代替。Linux 借助 flags 位 MAP_ANONYMOUS 来实现。

p = (int*)mmap(NUll, 4, PROT_READ |PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1,0)

PS:因为没有指定文件名,所以只限于有血缘关系进程间通讯

类似方法还有 /dev/zero

int fd = open("/dev/zero", O_RDWR);

011mmap进程通信相关推荐

  1. Linux进程通信中IPC对象——IPC_PRIVATE与ftok

    在linux中,可以使用IPC对象来进行进程间通信.IPC对象存在于内核中,多进程可以操作同一个IPC对象.每个IPC对象都有一个唯一的编号,该编号是由系统分配的.那么不同的进程如何知道这个编号,进而 ...

  2. Linux下进程通信知识点学习笔记(一)

    4种主要事件导致进程创建: 系统的初始化: 执行了正在运行的进程所调用的进程创建系统调用: 用户请求创建一个进程: 一个批处理作业的初始化: 进程的终止: 正常退出: 出错退: 严重错误: 被其他进程 ...

  3. 跨进程通信,到底用长连接还是短连接

    一个完整的软件系统大多数情况下是由多个进程共同协作进行的,哪怕它们在同一台服务器上.所以,进程之间如何进行高效的通信至关重要. 单个应用程序+单个数据库这套基础开发套餐我相信每个人都经历过,甚至在初期 ...

  4. linux一个进程通知另外一个进程,Linux进程通信学习笔记

    一.为什么需要进程通信 1)数据传输 一个进程需要把它的数据发送给另一个进程. 2)资源共享 多个进程之间共享同样的资源. 3)通知事件 一个进程向另外一个进程发送消息,通知它发生了某事件. 4)进程 ...

  5. 大话android 进程通信之AIDL

    上一篇的service涉及到进程通信问题,主要解决办法是通过 messenger来发送消息,这也是Google推荐的进程通信方式,比较简单易懂嘛~~,messenger底层也是通过binder来实现的 ...

  6. Binder跨进程通信原理(三):Binder IPC实现原理

    1. 动态内核可加载模块 && 内存映射 正如上一章所说, 跨进程通信是需要内核空间做支持的. 传统的 IPC 机制如 管道, Socket, 都是内核的一部分, 因此通过内核支持来实 ...

  7. Binder跨进程通信原理(一):动态内核加载模块

    先上一张Binder 的工作流程图.(如果不清晰,可以 复制图片链接到浏览器 或 保存到本地 查看,我经常都是这样看图的哈) 一开始上手,陌生的东西比较多,But,其实并不复杂.喔,流程图是用 Pro ...

  8. Android中的跨进程通信方法实例及特点分析(二):ContentProvider

    1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据,Android系统给我们提供了Content P ...

  9. 【Binder 机制】进程通信 | 用户空间与内核空间 | MMU 与虚拟内存地址

    文章目录 一.进程通信 二.用户空间与内核空间 三.MMU 与虚拟内存地址 一.进程通信 进程隔离概念 : 系统中的进程存在 " 进程隔离 " , 出于对进程运行的保护 , 两个进 ...

最新文章

  1. 曾在字节实习的程序员小姐姐,教你一步提取动漫线稿!比用PS更清晰
  2. 算法训练 区间k大数查询
  3. Ubuntu-16.04 部署 OpenStack Ocata下
  4. (转)CentOS 7系统详细开机启动流程和关机流程
  5. kappa一致性检验教程_SPSS在线_SPSSAU_Kappa一致性检验
  6. 点融产品 VP 赵征宇:增长是一个探索人性的过程
  7. 动态规划原理介绍(附7个算例,有代码讲解)
  8. 谷粒商城---新增收货地址,设置默认地址实现
  9. linux应用程序逆向,Linux下查看并下载命令源码包(根据命令/应用程序逆向获取并且安装其所属源码包)...
  10. Multi-Architecture镜像制作指南已到,请查收!
  11. oracle数据库扩容方案_ORACLE数据库扩容
  12. oracle+st_geometry
  13. Maven学习总结(26)——maven update时,报:Preference node org.eclipse.wst.validation...
  14. 【Vue2.0】— 消息订阅与发布pubsub(二十)
  15. 功能安全 李艳文_李艳文:智能网联全新安全问题凸显 相关自动驾驶事故逐年增加...
  16. Delphi之TStrings和TStringLists类[转]
  17. AppBox v6.0中实现子页面和父页面的复杂交互
  18. Python爬取 201865 条《隐秘的角落》弹幕,发现看剧不如爬山?
  19. 锐捷交换机密码恢复操作
  20. MySQL备份文件.ibd、.frm、.MYD、.MYI的恢复教程

热门文章

  1. 线上展厅生产车间vr搭建 广州商迪
  2. Linux使用iPhone USB共享网络
  3. c++语言随机数函数,C/C++产生随机数函数简单介绍
  4. 124、基于51单片机的智能电表功率电量仿真系统设计
  5. python 气泡图 聚类_10大Plotly数据可视化美图及工具介绍
  6. 前端面试题汇总大全 -- 持续更新!
  7. 蓝桥杯——第八届省赛_基于单片机的电子钟程序设计与调试
  8. java implements关键字_Java implements 关键字(keyword)
  9. JS鼠标事件onMouseOver和onMouseOut的坑
  10. ipguard,IM文件传送策略