内存管理—— malloc 细节

古装美女

1. 应用程序内存布局

在 Linux 系统中,应用程序的内存被分为若干个逻辑段,如图:


应用程序内存布局

其中,各个分段的意义是:

  • 代码段:程序编译后的可执行代码(指令)存放区域,在编译时确定了,同一个程序在不同机器上、在同一个机器上的不同次运行,同一个方法的入口地址都是确定的
  • 数据段:存放程序已初始化的静态常量和全局变量
  • BSS 段:存放未初始化的静态常量和全局变量
  • 堆:动态分配的内存区域,从低地址向高地址增长,大小不固定
  • 栈:存放局部变量、函数调用上下文等,栈的大小在程序启动时就固定了,一般是 8MB,系统提供了参数可以修改
    在上述分段中,文件映射段和堆的内存是由程序动态分配的,通常使用 C 标准库的 mallocmmap 方法来执行

2. malloc 是如何分配内存的

2.1 malloc 概述

实际上,malloc 是 C 标准库函数,而不是系统调用,mmapbrk 是系统调用,malloc 申请内存时有两种方式:

  • 方式一:通过系统调用 brk 从堆分配内存,具体方法是将堆空间的最高地址指针往高地址扩展,扩充堆区的大小
  • 方式二:通过系统调用 mmap 从文件映射区分配内存,具体方法是在文件映射区中找一块足够的空间,进行分配
    需要注意的是,此两种方式分配的都是 虚拟内存,并没有分配物理内存,那么什么时候进行物理内存的分配呢?在第一次访问虚拟空间时,查找页表失败,产生缺页中断,会进行物理分配的内存,并建立虚拟内存地址和物理内存地址的映射关系(生成页表项)

C 标准库中提供 malloc / free 函数分配和释放内存,这两个函数底层由 brk / mmap /unmap 等系统调用实现。

分别什么情况用 brkmmap 呢?
malloc 源码中定义了一个阈值 M_MMAP_THRESHOLD,默认为 128K

  • 当分配的值小于该阈值时,调用 brk
  • 否则,调用 mmap

2.2 一个例子

2.2.1 首先看看 brk 内存分配

图1-图3
  • 程序启动后,虚拟内存空间初始布局如图1 所示
  • 程序执行 A = malloc(30K) 后,执行系统调用 brk,将堆顶指针王高地址增加 30K,得到图2所示的内存布局。注意,此时只是完成了虚拟内存的分配,对应的物理内存还没分配,页表项也没创建,等到程序第一次读取 A 这块内存时,发生缺页中断,内核才会分配物理内存并建立对应页表项
  • 程序执行 B = malloc(40K) 后,同样的堆顶指针往高地址增加,如图3 所示

2.2.2 当 mmap 分配较大内存

图3-图6
  • 程序执行 C = malloc(200K),待分配的值超过了阈值,使用 mmap 分配,在堆和栈中间找一块空闲内存,并初始化为0,如图4所示。这样做的一个重要原因是,使用brk移动堆顶地址的方式分配内存,只有高地址的内存被释放后,才能释放低地址的内存,对于内存释放的顺序有依赖,如图4中,必须先释放 B ,才能释放 A,对于大块内存分配如果使用此种方式,将造成很多大块内存无法按需释放,而 mmap 分配的内存无依赖,可以单独释放

  • 程序执行 D=malloc(100k) 后,内存空间如图5所示

  • 程序调用 free(C) 释放内存,将 C 对应的 虚拟内存和物理内存一起释放,得到图6所示

2.2.3 内存的释放

图7-图9
  • 调用 free(B) 后的内存布局如图7,B 对应的虚拟内存和物理内存都没有释放,因为只有一个栈顶指针,由于 D 内存的存在,无法回推。当然,B 部分的内存是可重用的,此时如果来一个 40K 的分配请求,很可能就把 B 给分配返回了。
  • 程序执行 free(D) 后,内存布局如图 8 所示,B和D构成了一块 140K 的空闲内存
  • 系统默认当高地址空间的空闲内存超过 128K(由 M_TRIM_THRESHOLD 选项调节)时,会自动执行内存紧缩操作 (trim),在上一步 free(D)完成后,进行内存紧缩,内存布局变成图9所示,栈顶地址降低,释放对应的虚拟内存和物理内存

3. 总结

malloc 细节包括以下几点:

  • 当分配请求超过阈值时,使用 mmap 进行分配
  • 分配请求小于阈值时,使用 brk 分配
  • 分配时并没有立即分配物理地址,只是分配了虚拟地址,第一次访问时才建立页表项,分配物理地址
  • 释放 mmap 分配的地址时,可以立即释放
  • 释放 brk 分配的内存时,不会立即释放,但可以重用,执行释放时会检查堆顶指针附近的最大空闲块,如果超过阈值,则会执行内存紧缩策略,真正释放物理地址
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容