专栏首页移动开发面面观POSIX文件操作(二)

POSIX文件操作(二)

前言

上一篇中,我们学习了POSIX在<fcntl.h>帮助下的文件读写操作。主要使用writeread两个方法,以文件流的形式,进行读写。这一方法固然没有问题。但由于每次都需要I/O操作,在高频读写的场景,可能就会捉襟见肘了。

Linux为我们提供了mmap来解决这个场景下的问题。

基础知识

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。

初看起来,这个概念十分复杂。其实真的很复杂。。。简单来说,mmap通过一种方法将文件映射到内存中,我们修改内存即是修改文件。具体它与一般I/O操作有什么区别,可以参考:

从内核文件系统看文件读写过程 认真分析mmap:是什么 为什么 怎么用

使用范例

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

#define FILE_NAME "./test.txt"

int main(int argc, const char * argv[]) {
    
    int fd_open_create;
    char* buf;
    
    if((fd_open_create=open(FILE_NAME,O_CREAT|O_RDWR,0644))==-1)
    {
        perror("open");
    }
    printf("the %s file descriptor is:%d\n",FILE_NAME,fd_open_create);
    
    //取得文件状态)相关函数 fstat,lstat,chmod,chown,readlink,utime
    struct stat statbuf;
    if(stat(FILE_NAME,&statbuf)==-1)
    {
        //文件不存在
        perror("fail to get stat");
        exit(1);
    }
    // 建立内存映射,)用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。
    // 获取mmap映射内存
    buf=(char*)mmap(NULL,statbuf.st_size,PROT_WRITE|PROT_READ,MAP_SHARED,fd_open_create,0);
    if(buf==MAP_FAILED)
    {
        perror("fail to mmap");
        exit(1);
    }
    // 直接修改mmap映射内存
    buf[0]='6';
    //解除内存映射(在解除之前,文件已被修改,但系统并不保证已修改同步完成,可以自行加死循环验证)
    if(munmap(buf,statbuf.st_size)==-1)
    {
        perror("fail to munmap");
        exit(1);
    }
    // 采用read方式读取,验证文件内容
    char bufr[128];
    if( read(fd_open_create, bufr, statbuf.st_size) == 0)
    {
        perror("read");
    }
    
    printf("the %s file read content :\n%s\n",FILE_NAME , bufr);
    close(fd_open_create);
    return (EXIT_SUCCESS);
}

以上,就是mmap的基本使用。但是mmap并不是银弹。

mmap的场景

  • mmap之所以快,是因为建立了页到用户进程的虚地址空间映射,以读取文件为例,避免了页从内核态拷贝到用户态。
  • mmap映射的页和其它的页并没有本质的不同. 所以得益于主要的3种数据结构的高效,其页映射过程也很高效: (1) radix tree,用于查找某页是否已在缓存. (2) red black tree ,用于查找和更新vma结构. (3) 双向链表,用于维护active和inactive链表,支持LRU类算法进行内存回收.
  • (1) 对变长文件不适合. (2) 如果更新文件的操作很多,mmap避免两态拷贝的优势就被摊还,最终还是落在了大量的脏页回写及由此引发的随机IO上. 所以在随机写很多的情况下,mmap方式在效率上不一定会比带缓冲区的一般写快.

以上就是关于mmap的基本使用和一些基础知识,如有问题,欢迎指正。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android中基于OpenGL的特效

    大家都知道,给图片加滤镜加特效,通常是对图像进行矩阵运算。通过颜色矩阵的乘法,我们可以对图像中的元素进行变换。 但是,如果需要对实时变化的图像进行实时处理,就...

    Oceanlong
  • Git使用教程

    1、GIT是分布式的,SVN不是:这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。

    Oceanlong
  • Android dependencies 基础知识

    在build:gradle2.x的时代,我们在进行第三方依赖时,会有一些尴尬的问题。比如,我们制作了一个库,依赖了Glide2.0 。项目组集成我们的库,同时也...

    Oceanlong
  • iOS文件内存映射——MMAP

    最近一段项目上总是出现一些因为文件没有及时保存而产生的问题,因此小编就在网上寻找到了这个文件存储方法mmap,这里为大家进行下简单的介绍。

    用户5521279
  • iOS的文件内存映射——mmap

    mmap在日常开发中偶尔会遇到的一个关键词,最常用到的场景是MMKV,其次用到的是日志打印。虽然都已经被封装好,但也需要了解下mmap的基本原理和过程。

    落影
  • 认真分析mmap:是什么 为什么 怎么用【转】

    mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关...

    233333
  • 【数据】数据驱动决策的13种思维

    小编邀请您,先思考: 1 如何让数据驱动决策? “数据驱动决策”,为了不让这句话成为空话,请先装备以下13种思想武器,相信将来你一定能用上! 1. 信度与效度...

    陆勤_数据人网
  • 干货 :数据驱动决策的13种思维

    “数据驱动决策”,为了不让这句话成为空话,请先装备以下13种思想武器,相信将来你一定能用上! 第一、信度与效度思维 这部分也许是全文最难理解的部分,但我觉得也...

    灯塔大数据
  • 数据驱动决策的13种思维

    “数据驱动决策”,为了不让这句话成为空话,请先装备以下13种思想武器,相信将来你一定能用上! 第一、信度与效度思维 这部分也许是全文最难理解的部分,但我觉得也...

    小莹莹
  • 数据驱动决策的13种思维

    “数据驱动决策”,为了不让这句话成为空话,请先装备以下13种思想武器,相信将来你一定能用上!

    华章科技

扫码关注云+社区

领取腾讯云代金券