malloc 底层实现及原理

2023-11-04

原文:malloc 底层实现及原理 - 爱笑的张飞 - 博客园


摘要:偶尔看到面试题会问到 malloc 的底层原理,今天就来记录一下,毕竟学习要“知其所以然”,这样才会胸有成竹。

注:下面分析均是基于 linux 环境下的 malloc 实现。步骤是:先总结结论,再逐步展开

结论

1)当开辟的空间小于 128K 时,调用 brk()函数,malloc 的底层实现是系统调用函数 brk(),其主要移动指针 _enddata(此时的 _enddata 指的是 Linux 地址空间中堆段的末尾地址,不是数据段的末尾地址)

2)当开辟的空间大于 128K 时,mmap()系统调用函数来在虚拟地址空间中(堆和栈中间,称为“文件映射区域”的地方)找一块空间来开辟。

具体内容

当一个进程发生缺页中断的时候,进程会陷入核心态,执行以下操作:

1)检查要访问的虚拟地址是否合法

2)查找/分配一个物理页

3)填充物理页内容(读取磁盘,或者直接置0,或者什么都不做)

4)建立映射关系(虚拟地址到物理地址的映射关系)

5)重复执行发生缺页中断的那条指令

如果第3布,需要读取磁盘,那么这次缺页就是 majfit(major fault:大错误),否则就是 minflt(minor fault:小错误)

内存分配的原理

从操作系统角度看,进程分配内存有两种方式,分别由两个系统调用完成:brk 和 mmap (不考虑共享内存)

1)brk 是将数据段(.data)的最高地址指针 _edata 往高地址推

2)mmap 是在进程的虚拟地址空间中(堆和栈中间,称为“文件映射区域”的地方)找一块空闲的虚拟内存。

这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。

具体分配过程

情况一:malloc 小于 128K 的内存,使用 brk 分配

将_edata往高地址推(只分配虚拟空间,不对应物理内存(因此没有初始化),第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系),如下图:

1、进程启动的时候,其(虚拟)内存空间的初始布局如图1所示

2、进程调用A=malloc(30K)以后,内存空间如图2:

malloc函数会调用brk系统调用,将_edata指针往高地址推30K,就完成虚拟内存分配

你可能会问:难道这样就完成内存分配了?

事实是:_edata+30K只是完成虚拟地址的分配,A这块内存现在还是没有物理页与之对应的,等到进程第一次读写A这块内存的时候,发生缺页中断,这个时候,内核才分配A这块内存对应的物理页。也就是说,如果用malloc分配了A这块内容,然后从来不访问它,那么,A对应的物理页是不会被分配的。

3、进程调用B=malloc(40K)以后,内存空间如图3

情况二:malloc 大于 128K 的内存,使用 mmap 分配(munmap 释放)

4、进程调用C=malloc(200K)以后,内存空间如图4

默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存

这样子做主要是因为:

brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的,因为只有一个_edata 指针,这就是内存碎片产生的原因,什么时候紧缩看下面),而mmap分配的内存可以单独释放。

当然,还有其它的好处,也有坏处,再具体下去,有兴趣的同学可以去看glibc里面malloc的代码了。

5、进程调用D=malloc(100K)以后,内存空间如图5

6、进程调用free©以后,C对应的虚拟内存和物理内存一起释放

7、进程调用free(B)以后,如图7所示

B对应的虚拟内存和物理内存都没有释放,因为只有一个_edata指针,如果往回推,那么D这块内存怎么办呢当然,B这块内存,是可以重用的,如果这个时候再来一个40K的请求,那么malloc很可能就把B这块内存返回回去了

8、进程调用free(D)以后,如图8所示

B和D连接起来,变成一块140K的空闲内存

9、默认情况下:

当最高地址空间的空闲内存超过128K(可由M_TRIM_THRESHOLD选项调节)时,执行内存紧缩操作(trim)。在上一个步骤free的时候,发现最高地址空闲内存超过128K,于是内存紧缩,变成图9所示

参考博客:https://www.cnblogs.com/dongzhiquan/p/5621906.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

malloc 底层实现及原理 的相关文章

  • 成员字段、构建顺序

    在 C 中 当执行如下所示的操作时 构造顺序是否得到保证 Logger Logger kFilePath logs runtime log logFile kFilePath 是的 施工顺序始终得到保证 但是 不能保证它与对象在初始值设定项
  • 如何向WebRequest添加参数?

    我需要从 Web 服务调用一个方法 所以我编写了以下代码 private string urlPath http xxx xxx xxx manager string request urlPath index php org get or
  • C# 中直接从 URL 获取图像尺寸

    我正在尝试使用以下代码直接从网络上获取图片的尺寸 string image http www hephaestusproject com csharp3 png byte imageData new WebClient DownloadDa
  • BufferBlock 连续

    我想使用以下方式实现消费者 生产者模式BufferBlock
  • 当 foreach 块的内容具有 Conditional 属性时,C# 编译器是否会对其进行优化?

    我正在工作中编写一些调试代码 我想知道我所做的是否会损害性能 让我们看一下代码 foreach var item in aCollection Debug WriteLine item Name 我知道 Debug 类使用 Conditio
  • 如何部署包含第三方 DLL 文件的 C# 应用程序?

    首先 我对部署了解不多 我希望我的问题有意义 我需要将 C 应用程序安装 部署到多个桌面 它需要一个第三方 DLL 文件 一个 C 库 lpsolve55 dll 对于那些感兴趣的人 它是一个免费的 MIP LP 求解器 请参阅 lpsol
  • PartialView Action 正在调用自身

    我有 MVC 应用程序 它用于从主视图 ProductMaster 将 ProductAreaGrid 列表显示为 PartialView 并且它将在局部视图内将 CreateProductArea 作为 PartialView 我的 Gr
  • 多线程 - 比单线程慢

    当我使用多个线程而不是单线程运行程序时 它会变慢 不是应该更快吗 该程序应该遍历从起始目录开始的所有目录 并查找并打印所有名为 X 的文件 代码如下 while done pthread mutex lock lock if list is
  • 根据 Active Directory 策略检查密码[重复]

    这个问题在这里已经有答案了 我有一个允许用户更改其 AD 密码的前端 有没有办法获取特定用户及其属性 长度 复杂性 的密码策略 例如细粒度 有没有办法根据此特定策略检查字符串 xyz121 编辑 我不想检查活动目录中存储的当前密码 我想检查
  • C# 反序列化过程中创建指向父对象的指针

    我有这样的课程 Serializable public class child public Parent parent Serializable public class Parent public List
  • 文件加密与解密问题

    我一直在尝试在 VC Express 2010 中加密和解密文件 我见过的所有教程和文档都需要两个FileStreams 来加密文件 一个用于读取未加密的版本 另一个用于加密 当我实际编写代码时 它不断抛出错误 告诉我它无法打开该文件 因为
  • 如何解决文件被另一个进程使用的问题?

    我一直在 VS NET 2010 中调试 没有任何问题 但现在无法建造 我收到错误 Unable to copy file filename to bin Debug filename The process cannot access t
  • 禁用实体框架的默认值生成(Code First)

    我数据库中有一个列不能为空 我想将其设置为默认值在数据库中 问题是实体框架似乎自己创建了一个默认值 例如 int gt 0 并且完全忽略了数据库中的默认值约束 有没有办法禁用实体框架的默认值 我发现您可以使用以下属性来装饰您的字段 Data
  • 在 Windows 上使用 C/C++ 开发时省略 msvcr100.dll?

    是否可以在 Windows 上使用 C C 进行开发而不链接到 msvcr100 dll 我知道这是 Windows 的标准 c 库 但我想知道如果我没有安装 Visual Studio 或 Redistributable 软件包 我的计算
  • 如何在 ASP.NET Core 项目中使用 MStest 测试 Ok() 结果

    我正在使用 MStest 来测试我的控制器 我想测试这个动作 HttpGet Name GetGroups public async Task
  • 文本框中“结束编辑”的事件

    我正在 winform c 中使用文本框 并使用文本在数据库中进行查询 但每次文本更改时 我都需要不断查阅文本框的文本 因此 对于这些 我使用 KeyUp 但这个活动太慢了 文本框编辑完成后是否会触发任何事件 我考虑完成2个条件 控制失去焦
  • 按 Enter 继续

    这不起作用 string temp cout lt lt Press Enter to Continue cin gt gt temp cout lt lt Press Enter to Continue cin ignore 或更好 in
  • 如何使 WinForms UserControl 填充其容器的大小

    我正在尝试创建一个多布局主屏幕应用程序 我在顶部有一些按钮链接到应用程序的主要部分 例如模型中每个实体的管理窗口 单击这些按钮中的任何一个都会在面板中显示关联的用户控件 面板包含用户控件 而用户控件又包含用户界面 WinForms User
  • 在 C# 窗口应用程序中运行 C/C++ 控制台应用程序?

    现在 我想开发一个简单的应用程序 因此我决定最快的编码方式是 C NET 但现在 我很难实现我需要的功能之一 我想做的是在 C 应用程序的窗口内运行 C C 控制台应用程序 就像在虚幻前端中一样 添加一点通信方式 以便我可以为控制台应用程序
  • 使用方法的状态模式

    我正在尝试使用方法作为状态而不是类来基于状态模式的修改版本来实现一个简单的状态机 如下所示 private Action

随机推荐

  • 基于FISCO构建第一个区块链应用——简易的资产管理的开发

    学习资源来自于官方文档 https fisco bcos documentation readthedocs io zh CN latest docs tutorial sdk application html 有也在学习FISCO框架的欢
  • windows系统装成Ubuntu或linux后,无线/有线网卡无法连接或找不到适配器;拯救者装linux找不到适配器

    一般这种原因 网上有很多说法 让装驱动啊 让换镜像源啊 还有升级内核的 还有升级系统的 apt get命令装驱动的等等 一般来说 在使用Ubuntu的时候遇到无线网卡的时候 网上的教程就够了 但有些型号的电脑是不可以的 比如我的是拯救者 就
  • 前缀和+哈希表

    文章目录 1 基础知识 1 1 哈希表 1 2 前缀和 1 3 同余定理 2 哈希表的应用 2 1 思路讲解 2 2 代码实现 2 3 复杂度 3 前缀和与哈希表 3 1 面试题 17 05 字母与数字 3 1 1 题目要求 3 1 2 思
  • 当神经网络的性能不好怎么办?

    20210209 0 引言 本次写这篇文章是因为最近在训练的过程中 遇到了这个问题 而遇到这个问题其实也挺奇葩 因为之前的时候 也遇到过 但是那时候没有这样想 没有往这个方向想也是因为现象不同 因此也因为这个问题让我反思 首先来说一下具体现
  • Android 网络请求方式

    前言 最近需要将Android 项目接入物联网公司提供的接口 所以顺便给大家分享一下Android中我们常用的网络请求吧 提醒大家一下 我们遇到接口需求 一定要先在Postman上测试接口是否正确 然后再去项目上写程序来请求接口 否则 请求
  • java代码混淆工具Jocky的介绍

    最近给的任务是代码混淆 以前没有接触过 所以只能从最基础的东西开始了解 主要应用的工具有jocky progard dex2jar apktool jd GUI 今天简单介绍一下jocky的作用 并附上其他参考教程链接 jocky是一款ja
  • This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its

    在自定义MySQL函数的时候报了如下错误 2017 07 01 08 58 30 HY000 1418 This function has none of DETERMINISTIC NO SQL or READS SQL DATA in
  • MySQL根据不同条件联查不同表的数据if/case

    MySQL根据不同条件联查不同表的数据 项目开发中遇到类似的需求 Mybatis 中的 lt if gt 标签只能判断where部分 不能满足要求 在网上查解决方法 好像并没有可以完美解决问题的方案 if和case可以从某一种角度实现效果
  • Java HashSet介绍、使用方法详解及底层实现分析

    目录 1 HashSet介绍 2 使用方法 2 1 添加元素 2 2 判断元素是否存在 2 3 删除元素 2 4 计算集合元素个数 2 5 迭代HashSet 3 底层实现分析 1 HashSet介绍 HashSet 基于 HashMap
  • Xilinx FPGA平台GTX简易使用教程(汇总篇)

    GTX简易使用教程 先 知其然 慢慢再研究 所以然 目录 一 GTX必备基础知识 二 时钟篇 三 复位与初始化 四 GTX IP核配置介绍 五 GTX收发测试 六 后记 一 GTX必备基础知识 虽说搬砖只需要会用IP就行 但是为了把砖搬好
  • PCB过孔 VIA

    一 过孔基本概念与作用 1 过孔定义 从印制电路板的一个表层延展到另一个表层的导通孔 2 过孔作用 过孔可以起到电气连接 固定或定位器件的作用 二 过孔分类 通孔 Plated Through Hole 这种孔穿过整个线路板表面 可用于实现
  • nestjs:定义字典类型

    参考 initialization Declare and initialize a Dictionary in Typescript Stack Overflow 解决方法 下面的id可以改为任何命名 var persons id str
  • 系统上关闭是意外的_24V直流无刷电机电磁刹车系统介绍

    24V直流无刷电机型号BLDC57是在顾客规定状况下 这款一款直流无刷电机 48V 785W 3000转提升电磁刹车 实际主要参数见下表 这款电机选用绿色环保行业的天之骄子 钕磁铁硼钢 确保机器设备的优良特性 这款电机带24V直流无刷电机B
  • Idea打maven jar 抛出异常:A JNI error has occurred

    问题描述 当项目依赖其他jar包的时候 打出的jar包执行出错 抛出这个异常 报错信息 Error A JNI error has occurred please check your installation and try again
  • Android Studio 4.2 Gradle窗口找不到uploadArchives任务

    问题描述 Android Studio升级到4 2以后 新建了一个项目 配置好了uploadArchives任务想上传到Maven仓库 结果发现Gradle窗口找不到Tasks 解决方式 参考的原文链接 https stackoverflo
  • (软考高级)信息系统项目管理师过关经验

    初次接触软考是在大二期间 偶然了解到计算机软件水平考试 便在大二上学期一次性通过了软件设计师 结果本科阶段再也没有时间去考这些证书了 直到读研阶段 忙里抽闲赶紧复习 本不报希望 竟然通过了 总结原因无非是如下几条 已有知识储备 从容对待考试
  • springbootapplication注解包括哪些注解_@SpringBootApplication 注解 详解

    简单介绍一下 SpringBootApplication注解都有哪些注解组合而成 SpringBoot 一 SpringBootApplication是SpringBoot的一个核心注解 也是一个组合注解 二 SpringBootAppli
  • 疑难杂症 解决Ubuntu16.04 蓝牙搜索不到附近设备 适用于18.04

    文章目录 1 问题描述 2 问题症结 3 解决办法 References 1 问题描述 打开蓝牙搜索设备无果 2 问题症结 终端下输入命令 dmesg grep i blue BCM Patch brcm BCM hcd not found
  • 遍历存储树节点

    import json def unit node dict dump dict 记录节点 dump val node val 遍历节点 for sub node in node sub nodes temp val 1 sub nodes
  • malloc 底层实现及原理

    原文 malloc 底层实现及原理 爱笑的张飞 博客园 文章目录 结论 具体内容 内存分配的原理 具体分配过程 情况一 malloc 小于 128K 的内存 使用 brk 分配 情况二 malloc 大于 128K 的内存 使用 mmap