Linux中mmap函数使用

Stella981
• 阅读 324

一、前言


除了标准的文件IO,例如open,read,write,内核还提供接口运行应用将文件map到内存,使得内存中的一个字节与文件中的一个字节一一对应。这就是今天要说的mmap,它在android中的用处非常多,比如binder,还有腾讯的开源的IO框架MMKV。这里简单记录下使用。

二、优势和缺势


  • 优势

    1 .读写文件避免了 read()write() 系统调用,也避免了数据的拷贝。
    2 .多个进程 map 同一个对象,可以共享数据。
    3 .可以直接使用指针来跳转到文件某个位置,不必使用 lseek() 系统调用。

  • 劣势

    1 .内存浪费。由于必须要使用整数页的内存。
    Linux中mmap函数使用
    mmap原理

三、mmap使用方法


#include <sys/mman.h>

void * mmap (void *addr,
             size_t len,
             int prot,
             int flags,
             int fd,
             off_t offset);
  • addr
    这个参数是建议地址(hint),没有特别需求一般设为0。这个函数会返回一个实际 map 的地址。

  • len
    文件长度。

  • prot
    表明对这块内存的保护方式,不可与文件访问方式冲突。
    PROT_NONE
    无权限,基本没有用
    PROT_READ
    读权限
    PROT_WRITE
    写权限
    PROT_EXEC
    执行权限

  • flags
    描述了映射的类型。
    MAP_FIXED
    开启这个选项,则 addr 参数指定的地址是作为必须而不是建议。如果由于空间不足等问题无法映射则调用失败。不建议使用。
    MAP_PRIVATE
    表明这个映射不是共享的。文件使用 copy on write 机制映射,任何内存中的改动并不反映到文件之中。也不反映到其他映射了这个文件的进程之中。如果只需要读取某个文件而不改变文件内容,可以使用这种模式。
    MAP_SHARED
    和其他进程共享这个文件。往内存中写入相当于往文件中写入。会影响映射了这个文件的其他进程。与 MAP_PRIVATE冲突。

  • fd
    文件描述符。进行 map 之后,文件的引用计数会增加。因此,我们可以在 map 结束后关闭 fd,进程仍然可以访问它。当我们 unmap 或者结束进程,引用计数会减少。

  • offset
    文件偏移,从文件起始算起。

如果失败,mmap 函数将返回 MAP_FAILED

四、Android中使用mmap


#include <jni.h>
#include <string>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <android/log.h>

extern "C"
JNIEXPORT void JNICALL
Java_com_example_mmap_1demo_MainActivity_writeTestNative(JNIEnv *env, jobject thiz) {
   
       

    std::string file = "/sdcard/mmap.txt";

    //可读可写,没有就创建,unix打开
    int m_fd = open(file.c_str(), O_RDWR|O_CREAT, S_IRWXU);

    //获取当前一页大小
    int m_size = getpagesize();
    //将空文件设置成4k大小,4096字节
    ftruncate(m_fd, m_size);
    //产生映射  页内容可以写入可以读取 映射内容可以共享
    int8_t * m_ptr = static_cast<int8_t *>(mmap(0, m_size, PROT_WRITE | PROT_READ, MAP_SHARED, m_fd,
                                                0));

    std::string data("这是一个mmap demo");
    //内存拷贝
    memcpy(m_ptr, data.data(), data.size());

    __android_log_print(ANDROID_LOG_ERROR, "mmap", "写入数据:%s", data.c_str());
}

这个demo通过mmap文件映射到内存,只需要通过内存拷贝memcpy向文件写入数据

点赞
收藏
评论区
推荐文章
技术小男生 技术小男生
2个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi/etc/profile2:按字母键i进入编辑模式,在最底部添加内容:JAVAHOME/opt/jdk1.8.0152CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jarPATH$JAVAHOME/bin:$PATH3:生效配置
刚刚好 刚刚好
2个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
晴空闲云 晴空闲云
2个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
1个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Wesley13 Wesley13
1年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
1年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
1年前
PHP中的NOW()函数
是否有一个PHP函数以与MySQL函数NOW()相同的格式返回日期和时间?我知道如何使用date()做到这一点,但是我问是否有一个仅用于此的函数。例如,返回:2009120100:00:001楼使用此功能:functiongetDatetimeNow(){
Wesley13 Wesley13
1年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
helloworld_28799839 helloworld_28799839
2个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue