进程间通讯之mmap文件共享

一、概念:什么是mmap?

  通过共享存储实现进程间通讯是一个主要的进程间通讯的方式。它包括磁盘文件的共享和内存的共享,以前总是关注内存的共享,而忽略了磁盘文件的共享,也就是这里要讲的mmap。mmap地址映射是Linux系统提供的一种功能强大的系统调用,最典型的应用是用于显卡内存的映射。同样,对于普通的硬盘文件也可以进行mmap系统调用。mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。

注:实际上,mmap()系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。

函数原型如下所示:

       #include <sys/mman.h>

       void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);  //建立映射

       int munmap(void *start, size_t length);  //解除映射

二、参数说明:

  start: 起始虚拟地址,是用户期望使用的虚拟地址,如果进程的虚拟地址空间允许,那么会优先使用该地址。注意:该虚拟地址必须按页尺寸对齐。

      length:映射的长度。

      prot:期望的内存保护,注意不要和打开文件时的属性冲突。属性有PROT_EXEC、PROT_READ、PROT_WRITE、PROT_NONE,分别为可执行、可读、可写、不可访问。

      flags:指明映像对象的类型。类型有:MAP_FIXED(只使用指定的start虚拟地址)、MAP_SHARED(与其他进程共享该映射)、MAP_PRIVATE(创建一个写拷贝的映射,保持数据不影响原有文件)。

      fd: 打开的文件句柄。

      offset: 指明在文件中的偏移,注意:偏移也必须按页尺寸对齐。     

    其中最难理解的是start参数,它填入的是程序员期望使用的虚拟地址。如果该虚拟地址不冲突,那么mmap系统调用返回的值就应该是该虚拟地址。

三、代码实例

本例是打开一个普通的文件,对其进行mmap,然后读取文件内容:

 

复制代码
复制代码
 1 #include <sys/mman.h> /* for mmap and munmap */
 2 #include <sys/types.h> /* for open */
 3 #include <sys/stat.h> /* for open */
 4 #include <fcntl.h>     /* for open */
 5 #include <unistd.h>    /* for lseek and write */
 6 #include <stdio.h>
 7 int main(int argc, char **argv)
 8 {
 9     int fd;
10     char *mapped_mem, *p;
11     int flength = 1024;
12     void * start_addr = 0;
13     if(argc<2)
14         {
15             printf("please input filename\r\n");
16             return 0;
17         }
18     fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
19     flength = lseek(fd, 1, SEEK_END);
20     write(fd, "\0", 1); /* 在文件最后添加一个空字符,以便下面printf正常工作 */
21     lseek(fd, 0, SEEK_SET);
22     mapped_mem = mmap(start_addr, flength, PROT_READ,        //允许读
23     MAP_PRIVATE,       //不允许其它进程访问此内存区域
24     fd, 0);
25     /* 使用映射区域. */
26     printf("%s\n", mapped_mem); /* 为了保证这里工作正常,参数传递的文件名最好是一个文本文件 */
27     close(fd);
28     munmap(mapped_mem, flength);
29     return 0;
30 }
posted @ 2016-02-08 17:00  jimshi  阅读(546)  评论(0编辑  收藏  举报