• 进程间通讯之mmap文件共享


    进程间通讯之mmap文件共享

    引文:

      个人名言:“同一条河里淹死两次的人,是傻子,淹死三次及三次以上的人是超人”。经历过上次悲催的面试,决定沉下心来,好好的补充一下基础知识点。本文是这一系列第一篇:进程间通讯之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
    ");
    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, "", 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
    ", mapped_mem); /* 为了保证这里工作正常,参数传递的文件名最好是一个文本文件 */
    27     close(fd);
    28     munmap(mapped_mem, flength);
    29     return 0;
    30 }
    复制代码

     四、输出结果:新建文件1.txt 随意输入一些内容即可

    [zhangzl@localhost mmap]$ ./ex01 1.txt
    2
    hello
    world.

  • 相关阅读:
    Java程序员必备后台前端框架--Layui【从入门到实战】(一)
    Java程序员必备后台前端框架--Layui【从入门到实战】(三)
    Java程序员必备后台前端框架--Layui【从入门到实战】(二)
    机器学习平台和深度学习平台
    python资源
    Wireshark使用入门(转)
    xxxxxxxxxxxxxxxxxxx
    大众字体
    起点字体
    pycharm调试技巧
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3277359.html
Copyright © 2020-2023  润新知