`
java-mans
  • 浏览: 11392486 次
文章分类
社区版块
存档分类
最新评论

Linux使用内存映射文件做内存池

 
阅读更多

因为最近项目中需要实现一个临时数据高速存储,所以最近对内存映射文件做了一下了解,写出来与大家分享一下,因为个人水平有限也许会有这样那样的问题也恳请大家指正。

mmap是linux内存映射文件,是将文件映射成为内存地址空间的一种方式,其实,方法很简单。

memfd = open(MEMFILE, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
memd = mmap(NULL, (sizeof(Type)) * size, PROT_WRITE | PROT_READ,
                MAP_SHARED, memfd, 0);
我们的程序现在拥有了一定的地址空间,代码中也获得了一个指向首地址的指针,那我们该怎么使用他呢?其实,大家想怎么用就怎么用,不过我们还是采用一定的方法将这些地址空间管理起来,定义一下结构体来对内存进行结构化管理:

/**
 * \struct NodeHeader
 * \brief 节点头
 */
struct NodeHeader {
    unsigned int         size;         /**< 内存尺寸 */
    bool                 isActive;     /**< 是否使用 */
    unsigned int         refCount;        /**< 引用数量 */
    NodeHeader           *next;
};


/**
 * \struct Node
 * \brief 节点
 */
struct Node {
    NodeHeader header;       /**< 节点头 */
    char       *data;         /**< 数据 */
};


/**
 * \struct NodeList
 * \brief 节点列表
 */
struct NodeList {
    NodeList           *next;
    unsigned int       size;         /**< 列表中节点的尺寸 */
    NodeHeader         *header;         /**< 节点 */
};

/**
 * \struct NodeContext
 * \brief 节点列表目录
 */
struct NodeContext {
    bool         isInit;          /**< 是否已经初始化*/
    unsigned int refCount;        /**<引用计数器 */
    NodeList     *list;           /**< 节点列表头 */
};

注意,以上结构体本身没有定义实际存储数据的空间,而是通过Node的data指针来指向数据的空间。我一般会在Node之后紧接着根据size大小的数据空间,在分配时直接将指针向下移动相应的数值就可以。这是malloc函数实现中brk ()函数要做的事情,我们自己来做来模拟实现其分配过程。

初始化节点很简单:

Node* allocNode(NodeList *list)
{
    Node *node = (Node *)nodeMem;
    node->header.size = list->size;
    if(!nodeContext->isInit) {
        node->header.refCount = 0;
        node->header.isActive = false;
    }
    node->data = nodeMem + sizeof(Node);
    nodeMem = nodeMem + sizeof(Node) + list->size; //注意,这里直接将指针移动过去一定的值来为实际数据保留相应的空间
    return node;
}
我们经过一系列初始化过程将这些连续的地址空间进行了分割,这样我们就可以通过自定义的接口来访问这些内存块了。不过提醒大家的是由于进程间映射的地址值不同,所以我们把地址一个放到了映射文件中,会造成地址访问的越界。所以以上基于指针的实现只能够用于进程内,不过大家完全可以只在映射文件中保存数据,通过不同进程中相同的内存结构来访问。还有一种方式就是模拟cpu变址寻址和Linux底层虚拟内存来实现,这样既可以拥有了结构化的数据,又拥有了指针访问的灵活性。

那我们如何获取数据呢?大家注意到我上面使用的都是POD数据,也就是说他们都是不会经过C++编译器优化的(如果用在C中就更不存在这个问题了),这里我们直接offset来实现由数据获得节点:

Node* getNode(char *data)
{
    return (Node *)(&(*data) - sizeof(NodeHeader));
}
上面的所有的过程都是简单的对内存区域的移动,记得有人说过“编程不过就是做一些加法或者将内存中的数据从一个地方搬到另一个地方”。



分享到:
评论

相关推荐

    linux mmap文件内存映射机制

    mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式...普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。

    Linux 下内存映射与分块读取速度测试程序

    使用每行的字符个数统计和 MD5 两个算法比较内存映射和分块直接读取文件的速度。

    哈工大 操作系统实验5 linux0.01内存地址映射 代码及相关提交

    这是关于地址映射的。这个是07级哈尔滨工业大学操作系统实验的辛勤劳动,下面的压缩包中包含源代码,及实验报告,最好自己搭建平台,本人在电脑中又装了 linux,希望给感兴趣的人看看,呵呵,如果是工大的学弟学妹的...

    关于内存映射

    内存I/O映射,允许我们将一个磁盘文件映射到内存中的一块缓存。这样,当我们从缓存中获取数据的时候,我们相当于读取了文件中相应字节的数据;我们像缓存中存放数据的时候,数据会被自动地写到文件中

    Linux共享内存实例及文件映射编程及实现原理.pdf

    Linux共享内存实例及文件映射编程及实现原理.pdf

    Linux内存管理编程

    1.实验目的 (1) 学习Linux内存编程方法,掌握Linux内存映射和解除映射的方法 (2) 掌握在内存打开文件和读取文件的方法

    疯狂内核之——Linux虚拟内存

    第四章 磁盘文件内存映射 182 4.1 内存映射的数据结构 182 4.2 内存映射的创建 184 4.3 内存映射的请求调页 194 4.4 刷新内存映射的脏页 203 4.5 非线性内存映射 210 第五章 页面的回收 215 5.1 页框回收概念 215 ...

    深入解析Linux内存管理ppt

    目录:页表管理 内核页表 物理内存 高端内存 地址映射 虚拟内存 地址空间 高速缓存 页框回收 交换机制 缺页异常 共享内存 文件映射 程序执行

    linux 内存共享实列

    linux 内存共享源代码,调试时遇到段错误,需设置映射文件的大小!

    mmkv:使用Redis API的内存映射文件中的数据结构

    MMKV:内存映射文件上的快速持久键值引擎 MMKV是BSD许可的,基于内存映射文件的快速持久键值引擎。 建筑MMKV 现在只能在Linux上编译。 要构建整个项目,只需键入make即可编译lib&tests。 它应编译为静态库并在src...

    LINUX内存管理

    这样就允许该模式根据系统需要来动态调整内存使用。 为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。由于这个原因,页面可以移出内存并放入磁盘中。这个过程称为交换,因为页面会被从内存交换到硬盘...

    包含LINUX内核同步、信号、内存、调度、文件系统.rar

    虚拟内存管理 包括 : 反向映射 , KSM , MMAP 映射 , 缺页中断 , 共享内存 , 进程虚拟地址空间管理 , 页面回收 ; 物理内存管理 包括 : 页面分配器 等 ; 内存管理 位于 下图 Linux 内核整体架构图 中的 内核空间 ;

    内存管理内存管理内存管理

    文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...

    cpp-mmf:封装用于POSIX或Windows的内存映射文件的C ++ 98库

    内存映射文件C ++库教程和参考 目的 这是一个库,适用于C ++ 98语言及其后续版本,用于利用字节格式将文件处理为字节,并利用POSIX兼容操作系统和Mi​​crosoft Windows提供的系统调用。 内容 该软件包由一个HTML...

    用于Linux的用户空间可映射dma缓冲设备驱动程序。_C_Makefile_下载

    \n通过打开设备文件(例如devudmabuf0)并映射到用户内存空间,或者使用read()write() 函数,可以从用户空间访问由u-dma-buf 分配的DMA 缓冲区。\nO_SYNC可以通过在打开设备文件时设置标志来禁用分配的 DMA 缓冲区的...

    Linux内核反向映射机制的详细资料说明

    Cheetah,曾为U-boot社区和Linux内核社区提交过若干补丁,主要从事Linux相关系统软件开发工作,负责Soc芯片BringUp及系统软件开发,喜欢阅读内核源代码,在不断的学习和工作中深入理解内存管理,进程调度,文件系统...

    深入分析Linux内核源码.chm

    6.2 Linux内存管理的初始化 6.3 内存的分配和回收 6.4 地址映射机制 6.5 请页机制 6.6 交换机制 6.7 缓存和刷新机制 6.8 进程的创建和执行 第七章 进程间通信 7.1 管道 7.2 信号(signal) 7.3 System V 的IPC机制 第...

    proc_maps_parser:一个轻量级的库,用于解析Linux的proc [pid] maps文件,该文件包含进程的内存映射

    一个轻量级的库,用于解析Linux的/ proc / [pid] / maps文件,该文件包含进程的内存映射 / proc / [pid] / maps 包含当前映射的内存区域及其访问权限的文件。 有关内存映射的更多信息,请参见mmap(2)。 #memory...

    操作系统(内存管理)

    文将对 Linux™ 程序员可以使用的内存管理技术进行概述,虽然关注的重点是 C 语言,但同样也适用于其他语言。文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半...

    Professional Linux Kernel Architecture

    内存管理:解释Linux内核中的虚拟内存管理机制、页面置换算法和内存分配器,包括页面映射、内存回收、内存碎片整理等。 设备驱动程序:介绍Linux内核中设备驱动程序的实现方法,包括字符设备驱动、块设备驱动、网络...

Global site tag (gtag.js) - Google Analytics