从malloc中窥探Linux内存分配策略

2023-11-12

    malloc函数是C/C++中常用内存分配库函数,本篇文章将以Linux平台上的malloc为剖析对象,深入了解分配一块内存的旅程。

malloc入门

     使用malloc,需要包含头文件 stdlib.h ,函数原型如下:

      extern void *malloc(unsigned int num_bytes);

     功能: 分配长度为 num_bytes的内存块,如果分配成功,则返回指向被分配内存的指针,否则返回空指针NULL,否则发生的情况,一般为系统堆上可用的内存上无法找到一块长度大于num_bytes的连续内存空间。

     特别情况:如果num_bytes为0,malloc成功分配0字节的空间,返回一个有效指针,但无法使用此指针。

     当内存不再使用时,应使用free函数将内存块释放。

     返回值类型为void*,表示未确定类型的指针,它可以强制转换为任何其他类型的指针。

     

     extern  free(void *FirstByte);

     功能: 将之前malloc分配的空间还给操作系统,释放传入指针指向的那块内存区域,指针本身的数值没变,释放前,指向的内容是可理解的,释放后,指向的内容是垃圾内容。

     注意: 释放空指针,不会出错。释放同一个有效指针两次,会出错。释放后,最好把指向这块内存的指针指向NULL,防止后面的程序误用。

malloc深入了解

     glibc库实现了malloc,它实现linux系统的堆管理。在Linux中,大部分的系统调用都是通过C库函数来体现了,因此glibc就显得尤为重要。glibc的实现策略和Windows的类似,都是维护一个全局链表,每个链表元素由不定长的内存块链表。

    与Windows不同的是,在glibc中,维护了多个不定长的内存块链表,每一个链表负责一个大小范围,这种做法有效减少了分配大内存时的遍历开销,类似于哈希的方式,将很大的范围的数据散列到有限的几个小的范围内而不是所有数据都放在一起,虽然最终还是要在小的范围内查找,但是最起码省去了很多的开销,如果只有一个不定长链表那么就要全部遍历,如果分成3个,就省去了2/3的开销,总之这个策略十分类似于散列。glibc另外的策略就是不止维护一类空闲链表,而是另外再维护一个缓冲链表和一个高速缓冲链表,在分配的时候首先在高速缓存中查找,失败之后再在空闲链表查找,如果找到的内存块比较大,那么将切割之后的剩余内存块插入到缓存链表,如果空闲链表查找失败那么就往缓存链表中查找. 如果还是没有合适的空闲块,就向内存申请比请求数更大的内存块,然后把剩下的内存放入链表中。这种方式是glibc自己实现的策略。

     malloc函数,它内部有一个将多个可用内存块连接为一个空闲链表。在调用时,它沿链表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到链接表上。

     调用free函数时,它将用户释放的内存块回收到空闲链表。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。

《UNIX环境高级编程》第七章:

image

  从glibc中malloc的详细解释一文中知道:

  image

  在glibc的malloc实现中,分配虚存有两种系统调用可用,brk和mmap2,根据默认门限值来决定具体调用哪个进行分配。

image 

image

malloc返回的每块内存的起始处首先要有这个结构:

内存控制块结构定义
struct mem_control_block {
     int is_available;
     int size;
};

free函数比较简单,给出来。

4. 解除分配函数 free
void free(void *firstbyte) {
     struct mem_control_block *mcb;
/* Backup from the given pointer to find the
  * mem_control_block
  */
    mcb = firstbyte - sizeof(struct mem_control_block);
/* Mark the block as being available */
   mcb->is_available = 1;
/* That''s It!  We''re done. */
   return;
 }

    free函数中的第二句话,将传入指针倒回去内存控制块的大小,然后将该块中的is_available设置为1,将此空间标记为空闲空间,至于后续的回收整理,应该是操作系统和glibc内存管理模块来整理。从实现上看,释放的传入只能是分配内存块的首地址,而不能是中间的某个地址。

    从上述的free代码中来看,执行free函数后,堆上对应已分配内存已经标记为可用,但是这个可用内存空间经过多久才能被用户再次使用,这就取决于OS的内存管理策略,在还没将此块空间回收整理到空闲链表前,这块空间对用户来说,是不可用的。

 

参考资料:malloc和free的实现原理

             glibc的malloc-更多的改进

             glibc中malloc的详细解释

           

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

从malloc中窥探Linux内存分配策略 的相关文章

  • nslookup命令详解

    nslookup命令用于查询DNS的记录 查看域名解析是否正常 在网络故障的时候用来诊断网络问题 nslookup的用法相对来说还是蛮简单的 主要是下面的几个用法 1 直接查询 这个可能大家用到最多 查询一个域名的A记录 nslookup
  • Unique Binary Search Trees -- LeetCode

    原题链接 http oj leetcode com problems unique binary search trees 这道题要求可行的二叉查找树的数量 其实二叉查找树可以任意取根 只要满足中序遍历有序的要求就可以 从处理子问题的角度来
  • 操作系统笔记六(文件管理)

    1 文件逻辑结构 1 1逻辑结构的文件类型 分类 有结构文件 例如 PNG文件 无结构文件 1 2顺序文件 1 3索引文件 2 辅存的存储空间分配 2 1分配方式 连续分配 直接分配连续的存储空间 链接分配 隐式链接 在盘块内指定下一个盘块
  • 《一个操作系统的实现》读书笔记-- 第一章--最小的“操作系统”

    一 最简单的 操作系统 最最简单的 操作系统 就是一个最最简单的引导扇区 Boot Sector 虽然它不具有任何功能 但是它却能够直接在裸机上运行 不依赖其他软件 一个引导扇区是512个字节 并且以0xAA55为结束标识的扇区 下面就是那
  • 深入ftrace kprobe原理解析

    Linux krpobe调试技术是内核开发者专门为了编译跟踪内核函数执行状态所涉及的一种轻量级内核调试技术 利用kprobe技术 内核开发人员可以在内核的绝大多数指定函数中动态插入探测点来收集所需的调试状态信息而基本不影响内核原有的执行流程
  • 03LinuxC线程学习之线程共享和非共享

    1 线程共享和非共享 1 1 线程共享资源 1 文件描述符表 由于线程间共享进程间的内容 而文件描述符表在主线程的PCB当中 各个线程可以直接去请求访问 所以线程间通信就不需要像进程那样通过管道这些方式通信 2 每种信号的处理方式 即当某个
  • 算法问题实战策略

    算法问题实战策略 基本信息作者 韩 具宗万 译者 崔盛一出版社 人民邮电出版社ISBN 9787115384621上架时间 2015 2 4出版日期 2015 年3月开本 16开页码 738版次 1 1 内容简介 算法问题实战策略 本书收录
  • Elasticsearch 日志

    下载并安装 Filebeat 首次使用 Filebeat 请参阅入门指南 复制代码片段 curl L O https artifacts elastic co downloads beats filebeat filebeat 7 2 0
  • 自己动手写操作系统(一)

    本系列文章将一步步实现一个简单的操作系统 实验环境是在Linux系统下通过Bochs虚拟机运行我们自己写的操作系统 一 实验环境搭建 1 Ubuntu的安装 Windows用户可以选择在虚拟机中安装Ubuntu 具体安装教程可自行搜索 2
  • Linux 内核中的 Device Mapper 机制

    Linux 内核中的 Device Mapper 机制 尹 洋 在读博士生 尹洋 中科院计算所国家高性能计算机工程技术研究中心的在读博士生 主要从事服务部署和存储资源管理以及Linux块设备一级的开发和研究工作 简介 本文结合具体代码对 L
  • 由于回车符引起的shell错误

    今天弟弟写shell时出现一个错误 源代码如下 zip r 1 2 执行时出现错误 我也写了相同的语句 发现是可以执行的 把两个文件对比一看 差别在于 出错shell 正确shell 在linux下的回车是 n 在win下面的回车是 r n
  • 操作系统常见面试题

    1 什么是进程 Process 和线程 Thread 有何区别 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动 进程是系统进行资源分配和调度的一个独立单位 线程是进程的一个实体 是CPU调度和分派的基本单位 它是比进程更小的能
  • java IO、NIO、AIO详解

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 IO流 同步 阻塞 二 NIO 同步 非阻塞 三 NIO2 异步 非阻塞 正文 回到顶部 概述 在我们学习Java的IO流之前 我们都要了解几个关键词 同步与异步 sy
  • 如何快速构建CMBD系统-glpi

    脚本后续更新及迭代将由kkitDeploy项目代替 https github com luckman666 kkitdeploy server 请大家持续关注kkitDeploy 一 CMBD系统构建步骤 起初 开发这套CMBD系统是为了帮
  • MacOS中清除原有ssh公钥方法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 用ssh的跳转登录服务器后 ssh会把你每个你访问过计算机的公钥 public key 都记录在 ssh known hosts 当下次访问相同计算机时 SSH会核对公钥
  • 使用ShellJS提升你的开发效率(一)

    Shelljs Unix shell commands for Node js Shelljs是Node js下的脚本语言解析器 具有丰富且强大的底层操作 Windows Linux OS X 权限 Shelljs本质就是基于node的一层
  • RT-Thread 内存管理

    在计算机系统中 通常存储空间可以分为两种 内部存储空间和外部存储空间 内部存储空间通常访问速度比较快 能够按照变量地址随机访问 也就是我们通常所说的RAM 随机存储器 可以把它理解为电脑的内存 而外部存储空间内所保存的内容相对来说比较固定
  • 数组实现循环队列(增设队列大小size)

    目录 一 前言 1 如何实现循环 2 如何判断队列为空 3 如何判断队列为满 二 循环队列的结构定义 三 循环队列的创建及其初始化 四 入队 五 出队 六 取队头元素 七 取队尾元素 八 循环队列判空 九 循环队列判满 十 循环队列销毁 一
  • 按照层次遍历结果打印完全二叉树

    按照层次遍历结果打印完全二叉树 按照推论结果 l 层首个节点位置 2 h l 1 l 层节点间距 2 h l 1 1 编码实现 public static
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数

随机推荐

  • 膜拜(离散化差分模板题)

    题目描述 小鱼有 n 名优秀的粉丝 粉丝们得知小鱼将会在一条直线上出现 打算去膜他 为了方便 粉丝们在这条直线上建立数轴 第 i 名粉丝有一个侦查区间 li ri 如果小鱼在 j li j ri 处出现 这名粉丝将立刻发现并膜他 小鱼希望膜
  • python 3 中文URL编码转换问题

    链接里面含中文 转成URL编码 先引入模块 from urllib request import quote gt gt gt ff 摄像头 gt gt gt ff quote ff gt gt gt ff E6 91 84 E5 83 8
  • sql 还原数据库 错误3154

    在SQL Server2005及以下版本做数据库备份还原时 需要首先建立数据库 然后才能进行数据库还原操作 而在SQL Server2005以上版本做数据库还原时 不需要建立数据库 可以直接进行数据库还原操作 否则执行数据库还原操作时会报3
  • 求阶乘之和(循环版)(利用阶乘函数)

    请编写函数 用循环方法求阶乘之和 SumFac n 0 1 2 3 n include
  • uniapp uview 登录页

  • DETRs Beat YOLOs on Real-time Object Detection论文详解

    论文题目 DETRs Beat YOLOs on Real time Object Detection 论文地址 https arxiv org abs 2304 08069 论文代码 mirrors facebookresearch Co
  • jmeter:linux环境运行jmeter并生成报告

    是一个java开发的利用多线程原理来模拟并发进行性能测试的工具 一般来说 GUI模式只用于创建脚本以及用来debug 执行测试时建议使用非GUI模式运行 这篇博客 介绍下在linux环境利用jmeter进行性能测试的方法 以及如何生成测试报
  • matplotlib绘图与可视化2

    文章目录 前言 一 使用pandas和seaborn绘图 1 1 折线图 1 2 柱状图 1 3 直方图和密度图 1 4 散点图或点图 1 5 分面网格和分类数据 总结 前言 matplotlib是一个相当底层的工具 你可以从其基本组件中组
  • java ioc依赖注入,Spring bean的实例化和IOC依赖注入详解

    前言 我们知道 IOC是Spring的核心 它来负责控制对象的生命周期和对象间的关系 举个例子 我们如何来找对象的呢 常见的情况是 在路上要到处去看哪个MM既漂亮身材又好 符合我们的口味 就打听她们的电话号码 制造关联想办法认识她们 然后
  • 【带头结点的单链表】

    带头结点的单链表 前言 一 带头结点的单链表结构体设计 1 带头结点的单链表 2 结构体声明 二 函数实现 1 初始化 2 申请新节点 3 头插 4 尾插 5 按位置插入 6 头删 7 尾删 8 销毁 总结 前言 单链表的概念 单链表是一种
  • CS162 操作系统HW2(使用Liunx内核链表以及多线程实现WordCounter)

    心得体会 IDE自动提示补全真的特别重要 大大提高开发效率 通过IDE自动搜索库函数API GDB调试能力要加强 使用前面提供的list h来改写wordCount程序 头文件的实现相当有技巧 将使用外部list库 多线程都用宏定义到同一份
  • Could not load dynamic library ‘libcupti.so.10.0‘; dlerror: libcupti.so.10.0...

    环境 Ubuntu 16 04 CUDA 10 0 CUDNN 7 6 5 nvcc NVIDIA R Cuda compiler driver Copyright c 2005 2018 NVIDIA Corporation Built
  • ESP32 /ESP8266在VS Code and PlatformIO上传文件系统 (SPIFFS)

    ESP32 ESP8266在VS Code and PlatformIO上传文件系统 SPIFFS 学习如何上传文件到ESP32板文件系统 SPIFFS 使用VS Code与PlatformIO IDE扩展 快速和简单 使用ESP32的文件
  • 【计算机毕业设计】课堂考勤微信小程序 基于微信小程序的课堂考勤管理系统

    毕设帮助 源码交流 技术解答 见文末 一 前言 在目前国内的高校课堂考勤中 传统的到场点名方式耗费了教师大量的时间和精力 随着课堂人数的增加 学生群体呈现多样性 这种点名考勤方式将不再适合日常使用 而且传统的点名考勤无法避免代人答到现象 极
  • 包装类这颗语法糖,其实并不甜

    历史文章推荐 你真的了解时间吗 细数ThreadLocal三大坑 内存泄露仅是小儿科 Java 8 ConcurrentHashMap源码中竟然隐藏着两个BUG ConcurrentHashMap中有十个提升性能的细节 你都知道吗 Hash
  • 2023年及以后语言、视觉和生成模型的发展和展望

    一 简述 在过去的十年里 研究人员都在追求类似的愿景 帮助人们更好地了解周围的世界 并帮助人们更好地了解周围的世界 把事情做完 我们希望建造功能更强大的机器 与人们合作完成各种各样的任务 各种任务 复杂的信息搜寻任务 创造性任务 例如创作音
  • 如何在jieba分词中加自定义词典_R-数据挖掘

    一 jiebaR主要函数 1 worker 加载jiebaR库的分词引擎 worker type mix dict DICTPATH hmm HMMPATH user USERPATH idf IDFPATH stop word STOPP
  • 少儿编程竞赛概览

    少儿编程竞赛概览 全国性竞赛活动名单的确定 最终确定的 29 项中的信息类竞赛 学编程的孩子可以报哪些比赛 CSP J S 计算机非专业组别能力认证 全国中小学生创 造大赛 蓝桥杯青少年创意编程比赛 全国青少年编程创意与智能设计大赛 全国中
  • Ubuntu系统操作指令详解

    Ubuntu系统操作指令详解 解压文件指令 vim使用指令 1 进入编辑模式 2 退出编辑模式 ls alh显示出来内容的意思 创建文件夹 创建文件 删除当前文件夹下所有文件 ubuntu删除命令记录的方法 Ubuntu中复制文件出现权限不
  • 从malloc中窥探Linux内存分配策略

    malloc函数是C C 中常用内存分配库函数 本篇文章将以Linux平台上的malloc为剖析对象 深入了解分配一块内存的旅程 malloc入门 使用malloc 需要包含头文件 stdlib h 函数原型如下 extern void m