c语言基于mmap实现的内存池

文章目录

    • 0. 概要
    • 1. mmap基础
    • 2. 为什么使用内存池?
    • 3. 使用示例
    • 4. 设计考虑
    • 5. 实现步骤

0. 概要

c语言基于mmap实现的内存池模块
仓库地址: https://gitee.com/liudegui/mem_allocator_c

1. mmap基础

mmap系统调用在进程的虚拟地址空间和某个文件对象或匿名存储之间建立映射关系。当使用mmap进行内存映射时,操作系统会创建一个映射,使得对这段内存的访问就像对文件的读写一样。

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
  • addr:建议的映射起始地址(通常设为NULL,由系统决定)。
  • length:映射区域的长度。
  • prot:期望的内存保护标志(如PROT_READ, PROT_WRITE等)。
  • flags:影响映射区域的各种特性(如MAP_SHARED, MAP_PRIVATE等)。
  • fd:被映射对象的文件描述符,或者使用-1来表示匿名映射。
  • offset:文件映射的起始位置。

2. 为什么使用内存池?

  1. 提高效率:内存池可以减少向操作系统申请和释放内存的次数,从而提高内存分配的效率。
  2. 减少碎片:内存池可以有效地减少内存碎片,提高内存利用率。
  3. 便于管理:内存池可以将内存的申请、释放等操作集中管理,方便程序员进行内存调试和维护。

3. 使用示例

下面是一个基于C语言的内存池实现示例:

  • 头文件mem_allocator_c.h
/***Manager usage of vm mapped to /dev/mem 0x1000000~0x1dfffff*When create a MemPool, it's pool_ should be alloc use this class.*It will first alloc firstly try to alloc from memory map to /dev/mem.*If there is not enough memory in /dev/mem 0x1000000~0x1dfffff, it*will try to call calloc() func of stdlib to alloc memory.*/#ifndef UTILS_MEM_ALLOCATOR_C_H_
#define UTILS_MEM_ALLOCATOR_C_H_#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <stddef.h>#define MEM_ALLOC_DEFAULT 1
#define MEM_ALLOC_MAP 1
#define MEM_FD_INIT -1//=====================================================================
// MemMapMemAllocator
// Use MemMap to map /dev/mem 0x1000000-0x1dffefff into virtual memory.
// Use a linked table to store ranges in this mapping space. A range
// may be free or in-use.
//=====================================================================typedef struct MemAllocator MemAllocator;
typedef struct MemRange MemRange;
typedef struct MMapParams MMapParams;
typedef struct MemAllocDelegate MemAllocDelegate;#define MMAP_BASE_ADDR 0x10000000
#define MMAP_HIGH_ADDR 0x1DFFEFFFstruct MemRange {int8_t* offset;int8_t* end;uint32_t size;bool is_dirty;MemRange* next;MemRange* pre;
};struct MMapParams {MemRange* range_list;int32_t mem_fd;int8_t* map_base;uint32_t page_size;uint32_t base_addr;uint32_t high_addr;
};struct MemAllocator {int8_t* (*calloc)(MemAllocator* allocator, uint32_t nmemb, uint32_t size);void (*free)(MemAllocator* allocator, int8_t* buffer);char allocator_name[32];MMapParams* mmap_params;MemAllocator* next;
};struct MemAllocDelegate{MemAllocator* allocator;
};void init_mem_delegate(MemAllocDelegate* delegate, uint32_t base_addr, uint32_t high_addr);
int8_t* mem_delegate_calloc(MemAllocDelegate* delegate, uint32_t nmemb, uint32_t size);
void mem_delegate_free(MemAllocDelegate* delegate, int8_t* buffer);
void destroy_mem_delegate(MemAllocDelegate* delegate);#endif  // UTILS_MEM_ALLOCATOR_C_H_
  • 实现代码见: https://gitee.com/liudegui/mem_allocator_c
#include "mem_allocator_c.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>int main() {printf("hello world");MemAllocDelegate delegate;init_mem_delegate(&delegate, 0, 0);int8_t* p_addr = mem_delegate_calloc(&delegate, 10, 10);const char* const str = "hello world";memcpy(p_addr, str, strlen(str) + 1);printf("%s\n", p_addr);mem_delegate_free(&delegate, p_addr);destroy_mem_delegate(&delegate);return 0;
}

在这个示例中,我们首先定义了一个MemAllocDelegate结构体,用于存储内存池的信息。然后,我们通过init_mem_delegate函数初始化内存池,指定其大小和对齐要求。接下来,我们使用mem_delegate_calloc函数从内存池中分配一块内存,并将字符串"hello world"复制到这块内存中。最后,我们使用mem_delegate_free函数释放这块内存,并通过destroy_mem_delegate函数销毁内存池。

4. 设计考虑

在设计基于mmap的内存池时,需要考虑以下关键因素:

  1. 内存映射大小 :确定内存映射的大小是至关重要的。太小可能导致频繁地创建新的映射,而太大则可能造成内存浪费。
  2. 内存对齐 :确保内存分配满足特定硬件或软件的对齐要求。
  3. 内存保护 :设置合理的内存保护标志以避免越界访问。
  4. 内存清理 :在程序结束时,确保所有映射都被正确地释放。
  5. 错误处理 :正确处理mmap调用可能出现的错误,例如内存不足。
  6. 性能监控 :跟踪内存分配和释放的性能,以优化内存池的行为。

5. 实现步骤

  1. 初始化
    • 定义内存池结构体,包含必要的字段如mmap_paramsMMapMemAllocator等。
    • 初始化内存映射参数,包括页大小、映射大小等。
    • 调用mmap创建初始内存映射区域。
  2. 内存分配
    • 实现内存分配逻辑,根据请求的大小找到第一个合适的空闲区域。
    • 更新内存池的数据结构以反映分配情况。
    • 返回分配的内存区域的指针。
  3. 内存释放
    • 根据提供的指针找到对应的内存区域。
    • 更新内存池的数据结构以标记该区域为可用。
    • 如果有必要,合并相邻的空闲区域以减少碎片。
  4. 销毁
    • 遍历内存池的所有映射区域,调用munmap释放每个映射。
    • 清理内存池的数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/18920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

doxygen 1.11.0 使用详解(十四)——输出格式

目录 HTMLLATEXMan pagesRTFXMLDocBookCompiled HTML Help (a.k.a. Windows 98 help)Qt Compressed Help (.qch)Eclipse HelpXCode DocSetsPostScriptPDF The following output formats are directly supported by doxygen: HTML Generated if GENERATE_HTML is set to YES i…

时政|共享员工

概念 有人称“共享员工”就是变相的“劳务派遣”“外包”“临时工”&#xff0c;是对劳动者的变相压榨。专家表示&#xff0c;应从根源上理清“共享员工”的概念&#xff0c;否则会破坏正常的劳动合同秩序&#xff0c;无法让劳动者的合法权益得到有效保障。“共享员工”是指企…

被忽视的模块化领域:聚合、结算与执行层

原文标题&#xff1a;《Aggregation, settlement, execution》撰文&#xff1a;Bridget Harris 编译&#xff1a;Chris&#xff0c;Techub News 在关注度和创新方面&#xff0c;模块化堆栈的各个部分并不一样&#xff0c;虽然之前有许多项目在数据可用性&#xff08;DA&#xf…

[AI OpenAI] OpenAI董事会成立安全与保障委员会

这个新委员会负责就所有OpenAI项目的关键安全和保障决策提出建议&#xff1b;在90天内提出建议。 今天&#xff0c;OpenAI董事会成立了一个由主席Bret Taylor、Adam D’Angelo、Nicole Seligman和Sam Altman&#xff08;CEO&#xff09;领导的安全与保障委员会。该委员会将负责…

MySQL alter 语句

ALTER TABLE user ADD COLUMN cdkey varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT CD-Key, ADD COLUMN erp_userid varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT ERP用户ID, ADD UNIQUE INDEX un…

虹科Pico汽车示波器 | 免拆诊断案例 | 2017款吉利帝豪GL车发动机偶尔无法起动

故障现象  一辆2017款吉利帝豪GL车&#xff0c;搭载JLC-4G18发动机和手动变速器&#xff0c;累计行驶里程约为39.3万km。车主反映&#xff0c;该车发动机偶尔无法起动。故障发生频率比较频繁&#xff0c;冷机状态下故障比较容易出现。 故障诊断  接车后试车&#xff0c;故…

【Windows】本地磁盘挂载 Minio 桶

目录 1.软件安装安装winfsp支持安装rclone 2.新建rclone远程存储类型S3服务类型验证方式地区终端地址ACL服务端加密KMS 3.挂载存储盘 1.软件安装 安装winfsp支持 下载地址 或 下载地址2 文件为msi文件&#xff0c;下载后双击直接安装即可&#xff0c;可以选择安装路径 安装r…

Java多线程——线程强制执行

Join合并线程&#xff0c;待此线程执行完成后&#xff0c;再执行其他线程&#xff0c;其他线程阻塞。 可以想象成插队。 代码演示&#xff1a; //测试Join方法 //想象为插队 public class TestJoin implements Runnable{Overridepublic void run() {for (int i 0; i < 1…

手机号码携号转网查询保障用户权益、信息透明、优化用户体验

携号转网服务是指在同一本地网范围内&#xff0c;蜂窝移动通信用户&#xff08;不含物联网用户&#xff09;变更签约的基础电信业务经营者而用户号码保持不变的一项服务。近年来&#xff0c;随着通信行业的不断发展&#xff0c;携号转网服务已成为满足用户个性化需求、提升服务…

Strust2 远程代码执行漏洞[s2-005]

漏洞复现环境搭建请参考 http://t.csdnimg.cn/rZ34p kali切换jdk版本请参考 Kali安装JAVA8和切换JDK版本的详细过程_kali安装jdk8-CSDN博客 漏洞原理 Strust2会将http的每个参数名解析成为OGNL语句执行&#xff0c;OGNL表达式通过#来访问Struts的对象&#xff0c;并且通过过…

JS裁剪图片底部的水印

效果 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Image Popup</title><style>…

python dict字典

mapping 对象会将 hashable 值映射到任意对象。 映射属于可变对象。 目前仅有一种标准映射类型 字典。 &#xff08;关于其他容器对象请参看 list, set 与 tuple 等内置类&#xff0c;以及 collections 模块。&#xff09; 字典的键 几乎 可以为任何值。 不是 hashable 的值&am…

2024.05.14 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、校招 | 中核集团2025届校园招聘提前批正式启动&#xff01; 校招 | 中核集团2025届校园招聘提前批正式启动&#xff01; 2、实习 | 岚图汽车校园实习生招聘 实习 | 岚图汽车校园实习生…

达梦 结果拼接=多行结果返回一列字符串.

sql 转换 查询出多行数据 (select t.PROPERTY from JD_CODING t left join DELIVERY_OF c on t.VALUE c.TYPE where t.PROPERTY stackingType group by t.PROPERTY) 更改后 转为一列的拼接字符串 ( select listagg( distinct t.PROPERTY,,) within group ( order by t.P…

MiniPCIe/SATA双用插槽无法识别minipcie模块怎么回事!

在计算机和嵌入式系统设计中,MiniPCIe/SATA双用插槽作为一种高度集成的解决方案,提供了极大的灵活性与扩展能力。它不仅能够支持MiniPCIe接口的无线网卡、固态硬盘控制器等模块,还能适应SATA接口的硬盘或固态存储设备,大大丰富了系统配置的可能性。尽管设计初衷良好,但在实…

bert模型用于二分类问题微调

使用bert-base-chinese预训练模型对二分类问题进行微调 import pandas as pd from transformers import BertTokenizerFast, AutoModelForSequenceClassification, Trainer, TrainingArguments import torchmodel_name "./bert-base-chinese" path "./abuse_…

STP19NF20 丝印 19NF20 场效应管19A 200V 直插 TO-220

STP19NF20 功率MOSFET的应用领域相当广泛&#xff0c;主要包括&#xff1a; 1. 电源管理&#xff1a;用于高效率电源管理电路&#xff0c;如直流-直流转换器和交流-直流电源适配器。 2. 开关模式电源&#xff08;SMPS&#xff09;&#xff1a;在需要高效能和紧凑型尺寸的开关…

Ceph相关命令

关于osd自动重启 /etc/crontab里面每隔2分钟会调用 /etc/cron.daily/keep_osd.sh关闭osd 1 mv /etc/cron.daily/keep_osd.sh /etc/cron.daily/keep_osd.sh_back 2 systemctl stop ceph-osd0.service查看osd的参数 ceph daemon osd.0 config show |grep osd_op_num动态修改…

【学习】软件测试小伙伴,这几点助你提升软件测试水平

在数字化时代&#xff0c;软件已经无处不在&#xff0c;影响着我们的日常生活、工作乃至整个社会的运行。在这个背景下&#xff0c;软件测试成为确保产品质量的关键环节&#xff0c;关乎用户体验和社会信任。本文将为您梳理一些关于软件测试你必须了解的知识点&#xff0c;并阐…

JAVAEE之多线程进阶(2)_ CAS概念、实现原理、ABA问题及解决方案

前言 在并发编程时&#xff0c;常常会出现线程安全问题&#xff0c;那么如何保证原子性呢&#xff1f;常用的方法就是加锁。在Java语言中可以使用 Synchronized和CAS实现加锁效果。  Synchronized关键字保证同步的&#xff0c;这会导致有锁&#xff0c;但是锁机制存在以下问题…