视频地址:
http://player.bilibili.com/player.html?aid=31289365&bvid=BV1iW411d7hd&cid=100814374&page=19
http://player.bilibili.com/player.html?aid=31289365&bvid=BV1iW411d7hd&cid=161460550&page=20
课件地址:
对应于书中的9.9。
不能分配小于最小块大小的块。
虚拟页的存在是作为虚拟内存和物理内存传输数据块的单位,是由一系列连续的虚拟内存地址组成的,并且这些虚拟地址的特点由虚拟页定义。而虚拟内存段是将一系列大量的连续的具有相似特点的虚拟地址聚集起来,且虚拟内存段也描述了这些虚拟地址的一些特点,并且这些虚拟地址以虚拟页为单位进行组织,即虚拟内存段包含虚拟页。
我们使用虚拟内存时是以虚拟地址为单位的,只是根据我们对其使用方式的不同要求和权限,会处于不同虚拟段中的不同虚拟页中。
当调用malloc
函数来分配块时,首先会在空闲链表中寻找是否有合适的空闲块,如果尝试了合并空闲块还是没找到,则会调用sbrk
函数来向内核申请更大的堆内存。所以在一开始将堆与匿名文件映射时,堆内存为0,则第一次调用malloc
函数时,会直接调用sbrk
函数来申请得到一块大的空闲块,该空闲块可能会比你尝试分配的块大,然后就一直在这个堆中进行操作。
堆的起始地址到brk
之间是已申请的堆内存,可以在里面进行动态内存分配,而brk
之外的是未申请的堆内存,只有当找不到合适的空闲块时,才会向内核申请更大的可用空间,此时就会移动brk
。
除了上一章介绍的通过mmap
函数能让用户自定义内存映射,将磁盘文件映射到虚拟内存中以外,也可以在运行时使用动态内存分配器(Dynamic Memory Allocator)来分配额外的虚拟内存。动态内存分配器维护着虚拟内存中的堆段,将堆视为一组不同大小的块的集合,每个块由若干个连续的虚拟地址构成(一个块不一定处在同一个虚拟页),每个块具有两种状态:
而在最开始进行内存映射时,堆是与匿名文件关联起来的,所以堆是一个全0的段,即处于空闲状态,它紧跟在未初始的数据段后面,向地址更大的方向延伸,且内核对每个进程都维护了brk
变量来指向堆顶。
动态内存分配器具有两种类型,都要求由应用程序显示分配块,但是由不同实体来负责释放已分配的块:
malloc
来分配块,再通过free
来显示释放已分配的块,C++中的new
和delete
相同。