写点什么

Android C++ 系列:Linux 进程间通信 (二)

作者:轻口味
  • 2021 年 11 月 25 日
  • 本文字数:1096 字

    阅读完需:约 4 分钟

内存映射

mmap/munmap

mmap 可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存 地址,对文件的读写可以直接用指针来做而不需要 read/write 函数。


#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);
复制代码



如果 addr 参数为 NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果 addr 不是 NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择 addr 之上的某个 合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可以得到。len 参数是需 要映射的那一部分文件的长度。off 参数是从文件的什么位置开始映射,必须是页大小的整 数倍(在 32 位体系统结构上通常是 4K)。filedes 是代表该文件的描述符。


prot 参数有四种取值:


  • PROT_EXEC 表示映射的这一段可执行,例如映射共享库

  • PROT_READ 表示映射的这一段可读

  • PROT_WRITE 表示映射的这一段可写

  • PROT_NONE 表示映射的这一段不可访问


flag 参数有很多种取值,这里只讲两种,其它取值可查看 mmap(2)


  • MAP_SHARED 多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修 改,另一个进程也会看到这种变化。

  • MAP_PRIVATE 多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修 改,另一个进程并不会看到这种变化,也不会真的写到文件中去。


如果 mmap 成功则返回映射首地址,如果出错则返回常数 MAP_FAILED。当进程终止时,该进程 的映射内存会自动解除,也可以调用 munmap 解除映射。munmap 成功返回 0,出错返回-1。


下面做一个简单的实验。


qingkouwei@ubuntu:~$ vi hello qingkouwei@ubuntu:~$ cat hellohelloworldqingkouwei@ubuntu:~$ od -tx1 -tc hello0000000 68 65 6c 6c 6f 77 6f 72 6c 64 0a0000013
复制代码


使用 mmap 映射


#include <stdlib.h> #include <sys/mman.h> #include <fcntl.h>int main(void){  int *p;  int fd = open("hello", O_RDWR);   if (fd < 0) {    perror("open hello");    exit(1);   }  p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);   if (p == MAP_FAILED) {    perror("mmap");    exit(1);   }  close(fd);  p[0] = 0x30313233;   munmap(p, 6);   return 0;}
复制代码


  • 用于进程间通信时,一般设计成结构体,来传输通信的数据

  • 进程间通信的文件,应该设计成临时文件

  • 当报总线错误时,优先查看共享文件是否有存储空间

Unix Domain Socket

可以利用 socket 实现进程通信。

总结

本文介绍了 mmap 函数:mmap 可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存 地址,对文件的读写可以直接用指针来做而不需要 read/write 函数。

发布于: 2 小时前阅读数: 5
用户头像

轻口味

关注

🏆2021年InfoQ写作平台-签约作者 🏆 2017.10.17 加入

Android、音视频、AI相关领域从业者。 邮箱:qingkouwei@gmail.com

评论

发布
暂无评论
Android C++系列:Linux进程间通信(二)