Linux c/c++文件虚拟内存映射

简介: 这篇文章介绍了在Linux环境下,如何使用虚拟内存映射技术来提高文件读写的速度,并通过C/C++代码示例展示了文件映射的整个流程。
  1. 使用虚拟内存映射操作文件可以大大提高向文件之中写入数据的速率
  2. 文件映射虚拟内存编程模型

文件写入模型

  1. 打开文件 open()
  2. 修改文件大小 ftruncate()
  3. 挂载映射 mmap()
  4. 使用虚拟内存 指针方式
  5. 卸载映射 munmap()
  6. 关闭文件 close()
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

struct student{
    int id;
    char name[20];
    int age;
    double score;
};

int main(){
    //1.打开文件
    int fd = open("stu.dat",O_CREAT | O_RDWR);
    if(-1 == fd)
        printf("文件打开失败!\n"),exit(-1);
    else
        printf("文件打开成功!\n");
    //2.修改文件大小
    ftruncate(fd, 3*sizeof(struct student));
    //3.挂载映射
    struct student* p = mmap(NULL,3*sizeof(struct student),PROT_WRITE|PROT_READ,
        MAP_SHARED,fd,0);
    if((void*)-1 == p)
        printf("映射虚拟内存失败:%m\n"),close(fd),exit(-1);
    printf("映射虚拟内存成功!\n");
    //4.使用虚拟内存
    struct student* pp = p;
    pp->id = 1;
    strcpy(pp->name,"张三");
    pp->age = 33;
    pp->score = 1.33;
    pp++;

    pp->id = 2;
    strcpy(pp->name,"李四");
    pp->age = 44;
    pp->score = 1.44;
    pp++;

    pp->id = 3;
    strcpy(pp->name,"王二");
    pp->age = 22;
    pp->score = 1.22;

    printf("数据写入完成!\n");
    //5.卸载映射
    int ret = munmap(p,3*sizeof(struct student));
    if(ret){
        printf("卸载失败\n"),exit(-1);
    }else{
        printf("卸载成功\n");
    }
    //6.关闭文件
    close(fd);

    return 0;
}

文件读取模型

  1. 打开文件 open()
  2. 挂载映射 mmap()
  3. 使用虚拟内存 指针方式
  4. 卸载映射 munmap()
  5. 关闭文件 close()
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>

struct student{
    int id;
    char name[20];
    int age;
    double score;
};

int main(){
    //打开文件
    int fd = open("stu.dat",O_RDONLY);
    if(-1 == fd)
        printf("文件打开失败:\n"),exit(-1);
    printf("文件打开成功:\n");
    //挂载映射
    struct student* p = mmap(NULL,3*sizeof(struct student),PROT_READ,
        MAP_SHARED,fd,0);
    //读取数据
    struct student* pp = p;
    for(int i = 0;i < 3; i++){
        printf("%d:%s:%d:%g\n",pp->id,pp->name,pp->age,pp->score);
        pp++;
    }
    //卸载映射
    munmap(p,3*sizeof(struct student));
    //关闭文件
    close(fd);

    return 0;
}

void* mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

参数1: 映射区的开始地址,设置为0(NULL)时由系统决定映射开始地址

参数2: 映射区的长度

参数3: 期望的内存保护方式,不能与文件的打开模式冲突,它的值可以是下面值的组合

PROT_EXEC     //映射页内容可被执行
PROT_WRITE    //映射页可被写入
PROT_READ     //映射页可被读取
PROT_NONE     //映射页不可访问

参数4: 指定映射对象的类型,映射选项和映射页是否可以共享,它的值可以是下面值的组合

MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。

MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。

MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。

MAP_DENYWRITE //这个标志被忽略。

MAP_EXECUTABLE //这个标志被忽略。

MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。

MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。

MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。

MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。

MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。

MAP_FILE //兼容标志,被忽略。

MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当前这个标志只在x86-64平台上得到支持。

MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。

MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。

参数5: 文件描述符fd

参数6: 被映射文件的起始映射位置(即文件的偏移量)

int munmap(void *start, size_t length);

参数1: mmap()函数返回的地址

参数2: 映射虚拟内存的长度

函数返回值:

成功时: mmap函数返回被映射区的指针, munmap()返回0

失败时: mmap函数返回MAP_FAILED(void*)-1,munmap函数返回-1

相关文章
|
14天前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
|
14天前
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
|
23天前
|
算法 Linux 开发者
深入探究Linux内核中的内存管理机制
本文旨在对Linux操作系统的内存管理机制进行深入分析,探讨其如何通过高效的内存分配和回收策略来优化系统性能。文章将详细介绍Linux内核中内存管理的关键技术点,包括物理内存与虚拟内存的映射、页面置换算法、以及内存碎片的处理方法等。通过对这些技术点的解析,本文旨在为读者提供一个清晰的Linux内存管理框架,帮助理解其在现代计算环境中的重要性和应用。
|
6天前
|
存储 算法 安全
深入理解Linux内核的内存管理机制
本文旨在深入探讨Linux操作系统内核的内存管理机制,包括其设计理念、实现方式以及优化策略。通过详细分析Linux内核如何处理物理内存和虚拟内存,揭示了其在高效利用系统资源方面的卓越性能。文章还讨论了内存管理中的关键概念如分页、交换空间和内存映射等,并解释了这些机制如何协同工作以提供稳定可靠的内存服务。此外,本文也探讨了最新的Linux版本中引入的一些内存管理改进,以及它们对系统性能的影响。
|
29天前
|
存储 缓存 监控
|
2月前
|
存储 缓存 监控
Linux中内存和性能问题
【10月更文挑战第5天】
40 4
|
2月前
|
算法 Linux
Linux中内存问题
【10月更文挑战第6天】
58 2
|
26天前
|
缓存 算法 Linux
Linux内核中的内存管理机制深度剖析####
【10月更文挑战第28天】 本文深入探讨了Linux操作系统的心脏——内核,聚焦其内存管理机制的奥秘。不同于传统摘要的概述方式,本文将以一次虚拟的内存分配请求为引子,逐步揭开Linux如何高效、安全地管理着从微小嵌入式设备到庞大数据中心数以千计程序的内存需求。通过这段旅程,读者将直观感受到Linux内存管理的精妙设计与强大能力,以及它是如何在复杂多变的环境中保持系统稳定与性能优化的。 ####
32 0
|
2月前
|
存储 缓存 固态存储
|
7天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
21 2