zoukankan      html  css  js  c++  java
  • 内存控制mmap的原型和使用方法

    函数原型

    // 创建内存映射区
    #include <sys/mman.h>
    void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
    
    // 释放内存映射区
    int munmap(void *addr, size_t len); 
    

    形参:

    • addr:指定映射区域的首地址。通常传入NULL,表示让系统自动分配
    • length: 共享内存映射区的大小(小于等于文件的实际大小)
    • prot:共享内存映射区的读写属性, PROT_READ, PROT_WRITE
      • PROT_READ | PROT_WRITE 读写权限
    • flags:标注共享内存的共享属性。MAP_SHARED/ MAP_PRIVARE
    • fd:用于创建共享内存映射区那个文件描述符
    • offset:默认是0,表示映射文件全部。偏移位置 4K的整数倍

    返回值:

    • 成功: 返回映射区的首地址
    • 失败:MAP_FAILED, 和 errno

    mmap的使用例子

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <pthread.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    
    
    void sys_err(const char *str)
    {
        perror(str);
        exit(1);
    }
    
    void my_mmap(){
        char *p = NULL;
        int fd;
    
        //  需要先打开一个文件
        fd = open("testmap", O_RDWR|O_CREAT|O_TRUNC, 0644);
        if (fd==-1){
            sys_err("open error");
        }
        // 需要拓展文件大小, 这样可以拓展文件大小为11
        lseek(fd, 10, SEEK_END);
        write(fd, "", 1);
    
        //  获取文件长度
        off_t len = lseek(fd, 0, SEEK_END);
    
        // truncate,可以直接拓展文件大小
        ftruncate(fd, 10);  // 需要写权限才可以拓展文件大小
    
        p = mmap(NULL, len, PROT_READ|PROT_WRITE,
                 MAP_SHARED, fd, 0);
        if (p==MAP_FAILED){
            sys_err("mmap error");
        }
    
        // 使用p对文件进行读写操作
        strcpy(p, "hello mmap");  // 写操作
    
        printf("-----%s
    ", p);   // 读操作
    
    
        // 释放mmap空间
        int ret = munmap(p, len);
        if (ret==-1){
            sys_err("munmap error");
        }
    
    		close(fd);
    }
    
    
    int main() {
        my_mmap();
    }
    

    mmap的注意事项

    1. 用于创建映射区的大小为0, 实际指定非0大小创建映射区,会出现总线错误
    2. 用于创建映射区的文件大小为0, 实际制定0大小创建映射区,出无效参数
    3. 用于创建映射区的文件读写属性为,只读。映射区属性为读,写。出"无效参数"
    4. 创建映射区,需要read权限。因此,mmap的权限应该小于等于open权限。
    5. 文件描述符fd,在mmap创建映射区完成后即可关闭,后续访问文件,用地址访问
    6. offset必须是4096的整数倍
    7. 对申请的内存,不能越界访问。
    8. p++会直接修改p的内存地址,所有在释放的时候回出错,munmap释放的地址,必须是mmap返回的地址
    9. mmap的返回值必须要进行检查,因为非常容易出错
    10. 映射访问权限为”私有“MAP_PRIVATE, 对内存所做的所有修改,只在内存有效, 不会反应到物理磁盘上。
    11. 映射区访问权限为”私有“MAP_PRIVATE,只需要open文件时,有读权限,用于创建映射区即可。

    mmap的保险调用方式

    1. open的时候指定O_RDWR
    2. mmap(NULL, 有效文件大小, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

    mmap父子进程进行通信

    1. 先创建映射区。open打开
    2. flags需要使用MAP_SHARED进行共享映射
    3. 父进程要先进行创建映射区之后在fork创建子进程
    4. 一个进程读,一个进程写

    无血缘关系的进程通信

    1. 两个进程,打开同一个文件,创建映射区
    2. 指定flags为MAP_SHARED
    3. 一个进程写入,一个进程读出
    4. 注意一点:无血缘关系进程之间通信,mmap:数据可以重复读取,fifo数据只可以读取一次

    匿名映射

    • 匿名映射flag设置为MAP_ANONYMOUS
    • 不需要创建fd文件对象
    • len想要多长给多长
    • fd传入-1
    • 如果呢米有匿名flags的选项
      • /dev/zero --> "" ,随便取值多少
      • /dev/null ----> 随便怎么写入
  • 相关阅读:
    若没有任何实例包含Class Body 则enum被隐式声明为final
    Effective Java —— 多字段下考虑使用建造者模式构建实例
    Effective Java —— 用静态工厂方法代替构造器
    Java动态代理和CGLib代理
    Netty + Spring + ZooKeeper搭建轻量级RPC框架
    Netty学习摘记 —— UDP广播事件
    Netty学习摘记 —— 简单WEB聊天室开发
    Netty学习摘记 —— 心跳机制 / 基于分隔符和长度的协议
    Bugku 杂项 这是一张单纯的图片
    Bugku 杂项 签到题
  • 原文地址:https://www.cnblogs.com/fandx/p/12529502.html
Copyright © 2011-2022 走看看