首页 > 其他分享 >磁盘IO

磁盘IO

时间:2023-04-26 16:31:56浏览次数:27  
标签:文件 映射 mmap 读写 fd 内存 IO 磁盘

什么是mmap


mmap是一种系统调用,用于在进程地址空间和文件之间建立一个映射关系。通过mmap,进程可以将一个文件或其他对象的内容映射到它的地址空间中,从而实现对该文件或对象的访问。mmap可以提高文件读写的效率,并且可以在多个进程之间共享内存。在Linux系统中,mmap的实现是通过操作内核页表来完成的。


mmap是怎样提高读写效率的


mmap 可以提高文件读写效率的原因主要有两个:

  1. 避免了内核态和用户态之间的数据拷贝:在传统的文件读写中,文件数据需要从内核态的页缓存复制到用户态的缓冲区,或者反之。这个过程中需要频繁地进行上下文切换和数据拷贝,会消耗大量的 CPU 时间。而 mmap 将文件内容直接映射到进程的地址空间中,避免了数据拷贝,因此可以提高读写效率。

  2. 通过内存映射实现了文件的缓存:内存映射可以使文件数据直接缓存在内存中,避免了频繁地从磁盘读取数据,因此可以减少 I/O 操作的次数。此外,mmap 映射的文件内容会被分页存储在内存中,当需要访问某一页数据时,只需将该页从磁盘读入内存即可,而不必一次性将整个文件读入内存,这也可以减少 I/O 操作的次数,提高读写效率。


以下是使用 mmap 实现文件读写的示例代码:

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

#define FILESIZE (1024 * 1024)

int main(int argc, char *argv[])
{
    int fd, offset;
    char *data;

    /* 打开文件 */
    fd = open("file.txt", O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    /* 拓展文件大小 */
    if (ftruncate(fd, FILESIZE) == -1) {
        perror("ftruncate");
        exit(EXIT_FAILURE);
    }

    /* 将文件映射到内存中 */
    data = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (data == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    /* 将数据写入文件 */
    for (offset = 0; offset < FILESIZE; offset += 4096) {
        sprintf(data + offset, "Hello, World!\n");
    }

    /* 同步数据到磁盘 */
    if (msync(data, FILESIZE, MS_SYNC) == -1) {
        perror("msync");
        exit(EXIT_FAILURE);
    }

    /* 解除映射 */
    if (munmap(data, FILESIZE) == -1) {
        perror("munmap");
        exit(EXIT_FAILURE);
    }

    /* 关闭文件 */
    if (close(fd) == -1) {
        perror("close");
        exit(EXIT_FAILURE);
    }

    return 0;
}

上述代码实现了将一个大小为 1MB 的文件映射到内存中,并向其中写入 "Hello, World!\n" 字符串。下面是代码中各部分的解释:

  1. 打开文件:使用 open 系统调用打开一个名为 file.txt 的文件,并指定读写权限。如果打开失败,输出错误信息并退出程序。

  2. 拓展文件大小:使用 ftruncate 系统调用将文件大小设置为 1MB。如果操作失败,输出错误信息并退出程序。

  3. 将文件映射到内存中:使用 mmap 系统调用将文件 fd 映射到进程的地址空间中,并返回一个指向映射区域的指针 dataNULL 表示让内核自动选择映射地址,MAP_SHARED 表示映射区域可以被其他进程共享,PROT_READ | PROT_WRITE 表示映射区域可读可写。如果操作失败,输出错误信息并退出程序。

  4. 将数据写入文件:使用循环将字符串 "Hello, World!\n" 写入映射区域中。

  5. 同步数据到磁盘:使用 msync 系统调用将映射区域的内容同步到文件中。MS_SYNC 表示要求同步所有被修改的页,直到同步完成才返回。

  6. 解除映射:使用 munmap 系统调用将映射区域解除映射。如果操作失败,输出错误信息并退出程序。

  7. 关闭文件:使用 close 系统调用关闭文件。如果操作失败,输出错误信息并退出程序。

上述代码中,使用 mmap 将文件映射到内存中,避免了数据拷贝的过程,从而提高了文件读写的效率。同时,映射区域还可以缓存文件数据,避免了频繁地进行 I/O 操作,进一步提高了读写效率。使用 msync 将映射区域的内容同步到文件中,保证了数据的持久性。

需要注意的是,使用 mmap 时需要考虑内存的使用量,避免出现内存不足的情况。此外,还需要考虑多个进程同时访问同一映射区域时的同步问题。

标签:文件,映射,mmap,读写,fd,内存,IO,磁盘
From: https://blog.51cto.com/u_15855860/6228148

相关文章

  • torch+torchvision+cuda10.1
    torch1.7.1#CUDA10.1pipinstalltorch==1.7.1+cu101torchvision==0.8.2+cu101torchaudio==0.7.2-fhttps://download.pytorch.org/whl/torch_stable.html#CPUonlypipinstalltorch==1.7.1+cputorchvision==0.8.2+cputorchaudio==0.7.2-fhttps://download.pyt......
  • [PART 1-1] The Transaction
    Thischapteristalkingaboutsomeaffairshappenedinaschoolspeech.Iperceivethisastheauthorcasuallytalking.Butthissectionisstillageneraloutlineofthewholebook,OnWritingWell.Thesectionstartswiththeauthorbeinginvitedtoas......
  • (一)asyncio的基本使用框架,python高效处理数据,asyncio.gather(),asyncio. create_task
    asyncio是Python3.4引入的标准库,是一个基于事件循环的异步I/O并发库。它提供了一种协作式的多任务处理方式,使得我们能够在一个线程中并发处理多个I/O操作。它通过将I/O操作转化为异步的非阻塞调用,从而实现了高效的并发处理。其原理如下: 定义协程(coroutine):使用关键......
  • 解决 c3p0报错 Establishing SSL connection without server's identity verification
    解决c3p0报错EstablishingSSLconnectionwithoutserver'sidentityverificationisnotrecommended  ?useSSL=false<c3p0-config><default-config><propertyname="driverClass">com.mysql.jdbc.Driver</property>......
  • Android多进程时Application初始化问题
    原文地址blog.csdn.net之前在做项目时,遇到一个大坑,就是我的APP的Application的onCreate方法,竟然执行了好几次,这就导致我在onCreate里面做了一些初始化的操作被重复执行了,导致奇怪的bug产生。后来冷静下来分析一下,才发现有一些第三方组件,比如百度推送之类的,它们是单独开了一......
  • Android音频开发之AudioTrack
    原文地址www.jianshu.com在前两节中分享了Android音频开发之音频基本概念和Android音频开发之音频采集,本文分享的是如何使用AudioTrack来播放使用AudioRecord采集后的PCM数据。构造AudioTrack实例publicAudioTrack(intstreamType,intsampleRateInHz,intcha......
  • Correct the classpath of your application so that it contains a single, compatib
    1.背景有时候引入包有冲突,比如在Maven项目中的不同模块多次重复引入等这里遇到的问题是重复映入了如下包:<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0-RELEASE</vers......
  • Linux扩大虚拟机系统磁盘空间
    Linux扩大虚拟机系统磁盘空间一、基本步骤1.虚拟机保持关闭状态,设置->磁盘->拓展->最大磁盘大小 设成30G2.创建新分区3.格式化分区4.挂载分区(创建新分区后,需要挂载才能使用)5.解挂分区(解挂后,数据会保留,重新挂载,数据依旧存在)6.删除分区(删除后,数据不存在) 二、创建......
  • questions_01:500 Internal Server Error 解决思路
    500InternalServerError问题如何解决?结果令人啼笑皆非问题出现场景register.html:在利用ajax发送请求之后,我们手机会收到短信验证码,并且前端会收到后台的一个返回值,此时在我们的页面就要开始验证码倒计时,不知道什么原因就是显示不出来,后台运行代码也没报错,短信也是正常收......
  • wpf中IValueConverter的两种实现方式(key和静态实例)以及 ValueConversion 特性
    使用值转换器的场景:你得到一个值,你需要根据你的需求转成另一个东西,可以是图片、对象等等都行传入的是object,传出的也是object,使用值转换器需要继承接口:IValueConverter里面有两个方法Convert和 ConvertBackConvert很好理解:你把xaml中某个对象中的某个属性或其他值传递到Value......