接前一篇文章:Linux内核有什么之内存管理子系统有什么第二回 —— 单刀直入
本文内容参考:
系统调用与内存管理(sbrk、brk、mmap、munmap)
特此致谢!
上回讲到通过malloc()申请一个堆内的空间,底层要么执行brk(小内存分配),要么执行mmap(大内存分配)。二者之间的界限是MMAP_THRESHOLD(默认128KB)。小于等于MMAP_THRESHOLD的使用brk,大于MMAP_THRESHOLD的使用mmap。
先来看小内存分配。上一回中man malloc得到的说明中实际上提到了两个相关的系统调用:brk与sbrk。依旧在Linux终端下通过man brk查看其说明,如下所示:
两个系统调用的说明如下:
名称
brk,sbrk
原型
#include
int brk(void *addr);
void *sbrk(intptr_t increment);
说明
brk()和sbrk()改变程序间断点的位置,程序间断点就是进程数据段的结尾。(例如,程序间断点是未初始化数据段的结束之后的首个位置)。增加程序间断点具有为进程分配内存的效果;减少程序间断点则释放内存。
当addr参数合理、系统有足够的内存并且不超过最大值时,brk()函数将数据段结尾设置为addr,即间断点设置为addr(请参阅setrlimit(2))。
sbrk()将程序数据空间增加increment字节。当increment为0时则是返回程序间断点的当前位置。
brk()将break指针直接设置为某个地址,而sbrk()将break指针从当前位置移动increment所指定的增量。
返回值
brk()成功时返回0,失败返回-1并且设置errno值为ENOMEM。
sbrk()成功时返回之前的程序间断点地址。如果间断点值增加,那么这个指针(指的是返回的之前的间断点地址)是指向分配的新的内存的首地址。如果出错失败,就返回一个(void *) -1
并设置errno全局变量的值为ENOMEM。
注
避免使用brk()和sbrk():malloc(3)内存分配包是一种可移植且舒适的内存分配方式。
总结
brk()和sbrk()都用来改变 “program break”(程序间断点)的位置,改变数据段长度(Change data segment size),实现虚拟内存到物理内存的映射。
下一回开始结合代码,对于brk()和sbrk()进行详解。