• 【C语言】进程间通信之存储映射区mmap


    进程间通信之存储映射区mmap

    存储映射区mmap()

    存储映射区就是将一个磁盘文件映射到内存,通过操作内存,然后可以选择是否影响磁盘文件,从而修改磁盘文件。

    #include 
    void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
    int munmap(void *addr, size_t length);
    
    mmap返回值
        成功则返回系统分配的内存地址
        失败则返回MAP_FAILED
    munmap返回值
        成功则返回0
        失败则返回-1
    
    参数
        addr: 自己指定地址,或者设置为NULL,让系统分配。
        length: 打开文件的文件长度,使用lseek获取长度。
        prot: 映射区读写权限 
            读:PROT_READ 写:PROT_WRITE 执行:PROT_EXEC
        flags: 映射区的特性。
            MAP_SHARED: 写入映射区的数据会写回文件, 且允许其他映射该文件的进程共享。
            MAP_PRIVATE: 对此区域所做的修改不会写回原文件。
        fd: 打开文件的文件描述符
        offset: 打开文件的偏移量,通常设置为0,即不偏移
    

    示例:

    父子进程使用mmap进行通信

    //mmap.c
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main()
    {
        // void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
        // int munmap(void *addr, size_t length);
        int fd = open("./test", O_RDWR);
        if (fd < 0)
        {
            perror("open error");
            return -1;
        }
        int len = lseek(fd, 0, SEEK_END);
    
        void *addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        memset(addr, 0x00, strlen(addr));
    
        close(fd);
        if (MAP_FAILED == addr)
        {
            perror("mmap error");
            return -1;
        }
    
        int ret = fork();
        if (ret > 0)
        {
            // father
            memcpy(addr, "hello world", strlen("hello world"));
            wait(NULL);
    
            ret = munmap(addr, len);
            if (ret < 0)
            {
                perror("munmap error");
                return -1;
            }
            else
            {
                printf("mmap released\n");
            }
        }
        else if (ret == 0)
        {
            // child
            sleep(1);
            char *p = (char *)addr;
            printf("str is [%s]\n", p);
        }
        else
        {
            perror("fork error");
            return -1;
        }
    
        return 0;
    }
    //输出
    str is [hello world]
    mmap released
    

    匿名映射区

    添加匿名标志MAP_ANONYMOUS,并手动设置映射区大小

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main()
    {
        // void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
        // int munmap(void *addr, size_t length);
        // int fd = open("./test", O_RDWR);
        // if (fd < 0)
        // {
        //     perror("open error");
        //     return -1;
        // }
        // int len = lseek(fd, 0, SEEK_END);
        int len =4096;
    
        void *addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        memset(addr, 0x00, strlen(addr));
    
        //close(fd);
        if (MAP_FAILED == addr)
        {
            perror("mmap error");
            return -1;
        }
    
        int ret = fork();
        if (ret > 0)
        {
            // father
            memcpy(addr, "hello world", strlen("hello world"));
            wait(NULL);
    
            ret = munmap(addr, len);
            if (ret < 0)
            {
                perror("munmap error");
                return -1;
            }
            else
            {
                printf("mmap released\n");
            }
        }
        else if (ret == 0)
        {
            // child
            sleep(1);
            char *p = (char *)addr;
            printf("str is [%s]\n", p);
        }
        else
        {
            perror("fork error");
            return -1;
        }
    
        return 0;
    }
    //输出
    str is [hello world]
    mmap released
    

    最后

    推荐一个零声教育学习教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
    fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
    TCP/IP,协程,DPDK等技术内容,点击立即学习:链接

  • 相关阅读:
    408-2011
    【博学谷学习记录】超强总结,用心分享|Hive开窗函数
    JVM Optimization Learning(四)
    Node.js开发-path模块
    Vue知识系列(5)每天10个小知识点
    操作系统零拷贝技术、PageCache
    git打tag和版本控制规范
    记一次批量更新整型类型的列 → 探究 UPDATE 的使用细节
    使用ThreeJS绘制一个饼图
    delphi操作json
  • 原文地址:https://blog.csdn.net/qq_44653106/article/details/139723379