malloc与free的底层实现

2023-11-19

1本节引言

内存管理内幕

Linux内存管理:Malloc

本文引用了下面这篇文章,读完下面,应该读下上面两篇文章,其中,《内存管理内幕》提供了一个简单的malloc/free实现版本。看看它的free设计,相信有足够的吸引力(gnu free版本远比这复杂)

该篇文章基本把malloc与free的实现机制说清楚了。但是有些陷藏的东西没说清楚。Malloc实际上有很多版本(DougLea Malloc/BSD Malloc/Hoard Malloc/)

下面这些内容,对原文作了整理。

2 内存分配原理

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

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

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

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

3 malloc与free底层C实现

在标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由brk、mmap、,munmap这些系统调用实现的。

打开glibc内部malloc/free的malloc.c实现,malloc/free的实现都是复杂的。       

4 malloc内存分配过程

下面以一个例子来说明内存分配的过程,分别是小于128KB的内存分配与大小于128K的内存分配 (GNUmalloc的版本)

小于128K内存分配

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

 

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

其中,mmap内存映射文件是在堆和栈的中间(例如libc-2.2.93.so,其它数据文件等),为了简单起见,省略了内存映射文件。

_edata指针(glibc里面定义)指向数据段的最高地址。 

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

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

你可能会问:只要把_edata+30K就完成内存分配了?

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

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

 

大于128K内存分配

malloc大于128k的内存,使用mmap分配内存,在堆和栈之间找一块空闲内存分配(对应独立内存,而且初始化为0),如下图:

 

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

5.        默认情况下,malloc函数分配内存,如果请求内存大于128K(可由M_MMAP_THRESHOLD选项调节),那就不是去推_edata指针了,而是利用mmap系统调用,从堆和栈的中间分配一块虚拟内存。这样子做主要是因为:brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的,这就是内存碎片产生的原因,什么时候紧缩看下面),而mmap分配的内存可以单独释放。

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

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

7.        进程调用free(C)以后,C对应的虚拟内存和物理内存一起释放。

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

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

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

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

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

 

5 缺页中断

用ps -o majflt,minflt -C program命令查看缺页中断的次数。

majflt代表majorfault,中文名叫大错误,minflt代表minor fault,中文名叫小错误。

这2个数值表示一个进程自启动以来所发生的缺页中断的次数。

发生缺页中断后,执行了哪些操作?

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

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

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

3.        填充物理页内容(读取磁盘,或者直接置0,或者啥也不干) 

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

5.        重新执行发生缺页中断的那条指令 

如果第3步,需要读取磁盘,那么这次缺页中断就是majflt,否则就是minflt。 

转自:https://blog.csdn.net/vivitue/article/details/78266839

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

malloc与free的底层实现 的相关文章

  • 在宿主机查看docker使用cpu、内存、网络、io情况

    使用命令 docker stats OPTIONS CONTAINER docker stats命令返回一个用于运行容器的实时数据流 要将数据限制到一个或多个特定的容器 可以指定一个由空格分隔的容器名称或ID的列表 您也可以指定一个已停止的
  • 使用valgrind检查内存问题并且输出报告

    valgrind内存泄漏分析 是在linux中检查内存泄漏的工具 当程序编写完之后我一般都会使用它来检查一次内存问题 基本上能杜绝服务器的内存泄漏问题 当然是面对C C 这样的语言的 使用方式就是将程序编译好 然后通过valgrind来启动
  • uboot下内存操作mw和md命令详解

    mw简介 u boot 中的 mw 命令是用于向内存写入数据的命令 它有4种形式 mw b 写入 1 个字节 8 比特 的数据 mw w 写入 1 个字 2 字节 16 比特 的数据 mw l 写入 1 个长字 4 字节 32 比特 的数据
  • C/C++中二级指针传递参数【个人遇到内存值发生改变现象的记录及相关修正方法】

    目录 0 前言 1 二级指针传参奇怪现象 2 分析 3 解决方法 0 前言 在c c 中 时常会使用到主调函数通过参数去获取被调函数中的数值情况 针对这种情况 我前面也写过C C 主调函数从被调函数中获取 各种类型 数据内容方式的梳理归纳文
  • 内存四区(代码区 静态区 栈区 堆区)

    参考 内存四区 代码区 静态区 栈区 堆区 作者 今天天气眞好 发布时间 2021 04 01 18 09 13 网址 https blog csdn net qq 51118175 article details 115379779 sp
  • 频繁读写文件导致内存使用率过高

    最近接到一个客户反馈 说是服务器内存使用过高 总内存16G 使用top命令查看可用内存已经不足1G了 客户环境服务器为linux 部署了3个tomcat 每个tomcat均有大量的日志产生 让客户使用free m检查一下 此处有必要解释一下
  • C++堆内存分配

    C 堆内存分配 C堆内存分配 抽象与分层 如何扩展有效堆内存 brk和sbrk系统调用 如何维护有效堆内存 operator new 抽象与分层 c和c 的内存服务模型与计算机网络里面的协议分层模型有点类似 计算机网络协议大体分为 层 应用
  • java的各类型数据在内存中分配情况详解

    有这样一种说法 如今争锋于IT战场的两大势力 MS一族偏重于底层实现 Java一族偏重于系统架构 说法根据无从考证 但从两大势力各自的社区力量和图书市场已有佳作不难看出 此说法不虚 但掌握Java的底层实现对Java程序员来说是至关重要的
  • 文件相关操作

    1 文件相关概念 1 1文件的概念 一个文件通常就是磁盘上一段命名的存储区 但是对于操作系统来说 文件就会更复杂一些 例如 一个大文件可以存储在一些分散的区段中 或者还会包含一些操作系统可以确定其文件类型的附加数据 但是这些是操作系统 而不
  • c++ 获取磁盘总大小

    float WindowsInfo GetDiskTotal 单位 G all Total 0 函数外自定义 all Free 0 DWORD dwSize MAX PATH TCHAR szLogicalDrives MAX PATH 0
  • 资源池 'default' 没有足够的系统内存来运行此查询

    今天 有个客户突然打电话跟我说他的系统出了点问题 一个查询查了几十秒才出来 有时候还出不来 于是我上去看了一下 打开数据库看了相关视图 发现查询确实很慢 运行多次之后出现 资源池 default 没有足够的系统内存来运行此查询 嗯 这句话的
  • Linux mmap读/写触发共享文件页生命周期

    概述 Linux的mm内存子系统的核心功能就要要管理各种类型的page 确保能高效分配和释放 让物理内存得以最大化使用 初识内存系统往往关注的是page的申请和管理流程 容易忽略page的释放回收流程 其实理解mm中的内存回收和释放也是最核
  • Linux mmap系统调用视角看缺页中断

    问题 1 mmap具体是怎么实现比read write少一次内存copy的 2 mmap共享映射和私有映射在内核实现的时候到底有什么区别 3 mmap的文件映射和匿名映射在内核实现的时候到底有什么区别 4 父子进程的COW具体怎么实现的 概
  • Unity内存与资源管理

    内存管理是程序开发的核心问题 而资源的使用又与内存息息相关 因此本章想要梳理整个开发流程中Unity对于内存与资源的管理方式 一 内存基础 1 1 基础概念 内存是暂时存放CPU中的运算数据 与硬盘等外部存储器交换的数据 在操作系统中 内存
  • 关于野指针的一些问题与总结

    void Test void char str char malloc 100 strcpy str hello free str if str NULL strcpy str world printf str 请问运行Test函数会有什么
  • Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 如上图所示 首先java源代码文件 java后缀 会被java编译器编译为字节码文件 class后缀 然后再让类加载器加载各个类的字节码文件 加载完毕后 交由JVM执行引擎执行 在整个执行过程中 JVM会用一
  • [指针八]有关指针的面试题

    有关指针的经典面试题 C语言为何如此长寿并实用 C 为什么有那么多精彩 指针可以说是C C 中的灵魂所在 虽然早期中pascal也有指针 但是和C C 比起来不是一个级别的 今天为大家深入浅出的解析一下指针的有关笔试 面试题 所有题目来源网
  • CPU高速缓存SRAM命中问题的总结与实验

    1 SRAM高速缓存的结构 获取本机CPU的SRAM缓存信息 我使用的是一个叫cpuinfo x86的小程序 可以获取x86架构的cpu相关信息 下载地址 http osxbook com book bonus misc cpuinfo x
  • Eclipse打开时出现failed to create the java virtual machine...

    一 问题分析 关于Eclipse出现failed to create the java virtual machine 等情况 1 重装系统之后会发现eclipse很意外的打不开 2 有时候Eclipse使用的时间过长 3 以上情况都会出现
  • 作用域和内存问题

    文章目录 一 基本类型和引用类型的值 基本类型和引用类型的区别 1 动态的属性 2 复制变量值 3 传递参数 4 监测类型 二 执行环境及作用域 1 延长作用域链 2 没有块级作用域 一 基本类型和引用类型的值 变量可能包括两种不同的数据类

随机推荐

  • kMeans算法(K均值聚类算法)

    机器学习中有两类的大问题 一个是分类 一个是聚类 分类是根据一些给定的已知类别标号的样本 训练某种学习机器 使它能够对未知类别的样本进行分类 这属于supervised learning 监督学习 而聚类指事先并不知道任何样本的类别标号 希
  • 【100%通过率 】【华为OD机试真题 c++ 】最大数字【 2023 Q1 A卷

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 给定一个由纯数字组成以字符串表示的数值 现要求字符串中的每个数字最多只能出现2次 超过的需要进行删除 删除某个重复的数字后 其它数字相对位置保持
  • Android 模拟器 Genymotion 安装配置与 ARM 支持

    简介 Genymotion是一款基于x86架构的Android模拟器 由于系统启动速度 应用运行速度远远快于Android SDK自带模拟器而受到广泛应用 优缺点 优点 1 模拟器启动速度快 比AVD快很多 2 应用运行速度快 3 跨平台
  • Python面向对象类继承中发生的私有属性访问错误问题

    按照Python100days项目中的该方法来访问私有属性 可正常访问到 class Test def init self foo self foo foo def bar self print self foo print bar def
  • 【Pytorch】常用函数功能介绍和注意事项

    持续更新中 数据预处理 Variable from torch autograd import Variable 作用 自动微分变量 用于构建计算图 网络层定义 torch nn BatchNorm2d 设尺寸为N C H W 其中N代表b
  • 微信小程序实现点击左侧导航栏自动定位到对应的位置

    我要实现的效果是点击左侧导航栏 右侧区域会自动滚动到相应的位置显示 其中当选择品牌的时候 右侧是有索引栏的 效果图如下 刚开始的时候我是用微信小程序自带的组件scroll view是实现点击左侧导航栏的跳转功能 其中scroll into
  • C++ STL- 常用容器deque

    1 1 deque容器基本概念 功能 双端数组 可以对头端进行插入删除操作 deque与vector区别 vector对于头部的插入删除效率低 数据量越大 效率越低 deque相对而言 对头部的插入删除速度会比vector快 vector访
  • Xilinx 7系列芯片选型手册的资源量怎么看

    推荐阅读AMD官方文档 该文档介绍了各种资源的具体含义 链接 7 Series FPGAs Configurable Logic Block User Guide UG474 以XC7A35T为例 Logic Cells 逻辑单元 对于7系
  • QT new模态对话框

    1 如果父窗口是new出的 则子窗口如果用堆栈的方式 Dlg dlg 创建 则会出现QWSLock up down Invalid argument错误 这实际上QT4 8的一个Bug 如果不想重新编译Qt的话 可以采用以下方式临时避免一下
  • VSC/SMC(十六)——自适应鲁棒滑模控制

    目录 1 参数不定和扰动不定但有界的系统 2 滑模控制自适应律设计 2 1控制律设计总结 3 仿真分析 3 1 PD控制 3 2普通自适应律 3 3映射自适应律 3 4总结 4学习问题 1 参数不定和扰动不定但有界的系统 其中 2 滑模控制
  • lua json 库

    1 luajson GitHub mpx lua cjson Lua CJSON is a fast JSON encoding parsing module for Lua clone 源码 cd lua cjson 2 1 0 make
  • typescripe中的ajax和axios(一)

    typescript是基于JavaScript的 JavaScript中前端请求到后端使用的是Ajax Asynchronous JavaScript and XML 而在typescript中请求使用的axios axios是通过prom
  • ovirt节点添加windows虚拟机

    1 新建windows7虚拟机 设置Windows7镜像引导 2 启动起来后换盘安装驱动 换的是驱动盘 3 驱动安装成功后分区 再把系统盘换回来 开始装系统 4 等待装系统即可
  • 【Linux & IO多路转接】——epoll详解

    目录 一 epoll简介 二 epoll相关系统的调用 1 epoll create 2 epoll ctl 3 epoll wait 三 epoll工作方式 1 水平触发模式 level triggered LT 2 边缘触发模式 edg
  • C++征途 --- List链表容器

    第一部分 基础概念 上面这个模型的是一个单向链表 优点 1 链表增加和删除节点的时候不需要进行vector数组那样的增完后进行后移 也不需要删完后前移 当它增加一个节点的时候 只需要将它插入的位置的上一个节点的指针域中的指针指向增加的节点
  • 六、03【Java 多线程】之Java线程

    Java 创建线程的方式 Java创建线程有四种方式 继承 Thread 类 实现 Runnable 接口 实现 Callable 接口 使用 Executors 工具类创建线程池 1 继承 Thread 类 创建一个类继承 Thread
  • shell习题-被3整除

    1 要求 写一个脚本 计算100以内所有能被3整除的正整数的和 2 脚本答案 root liang 2018 06 23 vim 2018 06 23 sh bin bashfor i in seq 100 do Num i 3 if Nu
  • Vue踩坑记录(一)——vue,data属性为什么使用了_或$开头却会提示报错?

    我们先来看一个简单的例子
  • cityscapes和Mapillary Vistas两种不同分割数据集的label映射

    众所周知 cs一共有19类 但是Mapillary Vistas有很多类 在做domain adaption的时候 往往需要将二者的类别做一个映射 如下表 同时发现Mapillary Vistas这个数据集下载下来之后 对应的label咋i
  • malloc与free的底层实现

    1本节引言 内存管理内幕 Linux内存管理 Malloc 本文引用了下面这篇文章 读完下面 应该读下上面两篇文章 其中 内存管理内幕 提供了一个简单的malloc free实现版本 看看它的free设计 相信有足够的吸引力 gnu fre