美文网首页Linux 相关文章LinuxLinux学习之路
Linux 进程间通信(3) -- mmap共享映射区

Linux 进程间通信(3) -- mmap共享映射区

作者: wulegekong | 来源:发表于2017-02-10 17:50 被阅读0次

    进程间通信(IPC - InterProcess Communication)

    通信的方式有很多: 文件, 管道, 信号, 共享内存, 消息队列, 套接字, 命名管道等等;

    • 但是由于设计缺陷现在常用的有:
      1.管道(简单, 默认匿名管道, 还有有名管道)
      2.信号(开销小, 但是如果不是做系统编程一般不用, 因为缺点大于有点, 比如有没有收到无法确认)
      3.共享映射区(无血缘关系之间)
      4.本地套接字(最稳定)

    三、 共享映射区

    • 简述: 将本地磁盘上的文件映射(使用函数: void **mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);)到虚拟内存的加载动态库的区域, 这样便不用再去对文件进行操作, 直接对其内存上的地址进行操作就行了.
    • 通信: 父子进程共享内存映射区, 那么创建内存映射区之后再fork子进程即可直接进行操作; 无血缘关系的, 他们可以同时映射同一个本地文件, 在对其进行读写操作, 但是该文件里的数据是不需要的.(重点)
    • API:
    # include <sys/mman.h>
     void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
    参数: 
    void *addr: 内存中空间的地址, 以便映射, 但是我们是不知道的, 内核会处理, 一般传null
    size_t len: 映射的长度, 一般是和文件的大小对应, 但是你需要映射多大就写多少
    int prot: 映射区权限, 对应的是一些宏, 在man文档中查看, 我们一般都要用到读写权限: PORT_READ PORT_WRITE, 设置时必须有读权限
    int flags: 对应的宏, 一般如果通信使用一般设置成MAP_SHARED
    int fd: 映射的文件描述符
    off_t offset: 映射文件的偏移量, 对应磁盘文件的偏移量, 设置时必须是4K的整数倍, 不需要指定时传0即可
    返回值:
    调用成功返回映射区的首地址, 失败返回MAP_FAILED即(void *)(-1)
    
    • 映射区映射本地文件代码:
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    int main(int argc, const char* argv[])
    {
        int fd = open("test.txt", O_RDWR); //打开本地磁盘中的文件, 获取fd
        if(fd == -1) {
            perror("open error");
            exit(1);
        }
        void* ptr = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if(ptr == MAP_FAILED) {
            perror("mmap error");
            exit(1);
        }
        close(fd);
    
        printf("buf = %s\n", (char*)ptr);//读取数据
        // 修改映射区数据
        strcpy(ptr, "99999999999999");
        // 释放内存映射区
        int ret = munmap(ptr, 1024);
        if(ret == -1) {
            perror("munmap error");
            exit(1);
        }
        return 0;
    }
    
    • 注意:
    1 如果对mmap的返回值(ptr)做++操作(ptr++), 那么释放时调用munmap会失败
    2 如果open时O_RDONLY, mmap时prot参数指定
    PROT_READ | PROT_WRITE会怎样?--会提示权限不够, 因为文件打开的时候是reonly, 但是映射区对应的待会还要写操作, 但是文件没有该权限
    3 文件偏移量必须是4k的整数倍, 不然mmap出错
    4 调用mmap时要注意权限问题, 偏移量问题, 长度问题(长度必须大于0, 不然没意义, 并且要求本地文件大小也是大于0的, 文件长度>=映射区长度)
    5 open的时候O_CREAT一个新文件也可以来创建映射区但是前提是创建成功之后使用truncate(truncate)做文件拓展, fseek也可以拓展, 但是需要进行一次写操作
    6 映射区创建成功之后, 文件就可以关闭了
    7 对ptr越界操作会出现无效操作或段错误, 但是越界之后不会对文件有影响的
    

    相关文章

      网友评论

        本文标题:Linux 进程间通信(3) -- mmap共享映射区

        本文链接:https://www.haomeiwen.com/subject/hiagittx.html