从malloc中窥探Linux内存分配策略
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环境高级编程》第七章:

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

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

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的实现原理
从malloc中窥探Linux内存分配策略的更多相关文章
- Linux内存分配小结--malloc、brk、mmap【转】
转自:https://blog.csdn.net/gfgdsg/article/details/42709943 http://blog.163.com/xychenbaihu@yeah/blog/s ...
- java中内存分配策略及堆和栈的比较
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...
- 【java虚拟机序列】java中的垃圾回收与内存分配策略
在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...
- JVM中内存分配策略及堆和栈的比较
最近愈发对JVM底层的运行 原理产生了兴趣,遂查阅相关资料以备忘. 内存分配策略 根据编译原理的观点,程序运行时的内存分配,有三种策略,分别为静态的.堆式的.栈式的. 静态存储分配指的是在编译时就能确 ...
- CentOS的Redis内存分配策略配置
安装了一主两从节点,启动之后发现有一个警告: 大概是说overcommit_memory设置成了0,在低内存环境下后台保存可能会失败,设置成1重启可解决. 然后,不太懂这个配置的含义,google一把 ...
- 深入理解Linux内存分配
深入理解Linux内存分配 为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化.除此 ...
- Memcache 内存分配策略和性能(使用)状态检查
前言: 一直在使用Memcache,但是对其内部的问题,如它内存是怎么样被使用的,使用一段时间后想看看一些状态怎么样?一直都不清楚,查了又忘记,现在整理出该篇文章,方便自己查阅.本文不涉及安装.操作. ...
- 【转载】Ogre的内存分配策略
原文:Ogre的内存分配策略 读这个之前,强烈建议看一下Alexandrescu的modern c++的第一章关于policy技术的解释.应该是这哥们发明的,这里只是使用. 首先列出涉及到的头文件:( ...
- 《深入理解Java虚拟机》-----第3章 垃圾收集器与内存分配策略
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来. 3.1 概述 说起垃圾收集(Garbage Collection,GC),大部分人都把这 ...
随机推荐
- oc-21-class对象
/** 什么是类对象(Class对象)? 类在内存当中也是以对象形式进行存储的. 1.类对象的类型:Class类型 2.如何创建类对象: 1)Class 类对象名 = [类名 class]; 2)类名 ...
- MySQL · 引擎特性 · InnoDB 事务锁简介
https://yq.aliyun.com/articles/4270# zhaiwx_yinfeng 2016-02-02 19:00:43 浏览2194 评论0 mysql innodb lock ...
- Tomcat中部署WEB项目的四种方法
对Tomcat部署web应用的方式总结,常见的有以下四种: 1.[使用控制台部署] 访问Http://localhost:8080,并通过Tomcat Manager登录,进入部署界面即可. 2.[利 ...
- SSMTP—让Linux系统从Office 365发送邮件
SSMTP-让Linux系统从Office 365发送邮件 导读 SSMTP 是一个非常简单实用的小工具,它可以将 Linux 系统的电子邮件中继到 Office 365.Google 或其它第三方 ...
- php模拟多线程
一:应该知道的: php本身是不支持多线, 但是php的好搭档,apache和linux是支持的,故lamp才是最佳组合,还在使用win服务器的现在知道为什么要用linux吧.既然是模拟的, 就不是真 ...
- 内存映射mmap
Table of Contents 1. 什么是mmap 2. 使用方法 2.1. mmap构造器的格式 2.2. 例子1 2.3. 例子2 3. 其它 4. 参考资料 什么是mmap 通常在Unix ...
- C# 之 FileSystemWatcher事件多次触发的解决方法
1.问题描述 程序里需要监视某个目录下的文件变化情况: 一旦目录中出现新文件或者旧的文件被覆盖,程序需要读取文件内容并进行处理.于是使用了下面的代码: public void Initial() { ...
- 【Linux/Ubuntu学习2】ubuntu-ubuntu10.04使用wine安装SourceInsight
1. 环境:ubuntu10.04 2. 安装 wine 关于 wine ,请参考这里.通过网络安装: $ sudo apt-get install wine 3. 安装 SourceInsight ...
- 《MFC游戏开发》笔记四 键盘响应和鼠标响应:让人物动起来
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9327377 作者:七十一雾央 新浪微博:http:// ...
- json数据处理技巧(字段带空格、增加字段)
1.json数据的正常取值:json[i].fieldName 2.json数据的字段带空格:eval('json[' + i + ']["' + field + '"]') 3. ...