说到内存管理,你的脑海里有很多东西,但都比较碎片,段,页,malloc,虚拟内存,LRU各种东西在脑海中乱跳,但是让你说说,又说不清楚。那是因为你说的内存和你认为的内存可能是不同的东西。在不同维度上的内存,有不同的管理方式。从维度上内存分为:物理内存,内核内存,虚拟内存,进程内存。
物理内存管理:管理物理内存页的分配与释放,常用的方法有位图和链表。位图用于记录其伙伴是否位于队列中。
为什么是页:
连续分配
1) 固定分区分配,内部碎片
2) 动态分区分配,外部碎片
3) 可重定位分区分配,调整开销大
离散分配
分页:通过地址转换,讲逻辑上连续的地址大散,减少内存碎片
通过向量表分配和回收物理页。
内核内存管理:物理内存管理无法满足内核对内存的需求(不参与交换,使用时间短,动态分配和回收,尺寸小)。Slab分配器(基本概念是Cache和Slab)
Cache管理一组Slab,Slab管理一组大小相同的内存块。通过Slab与物理内存交互。
向对应的catch申请内存块,如果该catch没有slab或者slab中没有空闲的对象,创建行的slab并添加到catch的slab链表中。在slab列表中查找空闲对象,找到并分配。
虚拟内存管理:
Linux采用三级页表结构,
(虚拟内存的好处:大地址空间,进程保护,内存映射,虚拟共享,多进程同时驻留内存,运行时重定位,机器无关代码)。
地址映射,缺页中断,访问控制,页面交换。
地址映射:段页式管理,多级页表,MM,块表
缺页中断:虚拟地址中只有部分也映射了物理页,当访问没有映射物理页的虚拟地址时,会发生缺页中断,将磁盘中的内容调入到内存空闲页中,更新页表建立虚拟内存到物理内存的映射。物理内存时有限的,当没有空闲页的时候,需要将页面换出,腾出空闲。所以有页面替换算:FIFO,LRU,OPT,CLOCL
进程内存管理:
动态内存管理,malloc再虚拟内存中分配,底层使用mmap和brk系统调用。分配大内存块的(大于128k)时,使用mmap在堆和用户栈之间找一段空闲虚拟内存。Brk提升brk指针增加堆内存。
被释放的堆内存为空闲内存,空闲内存通过空闲链表组织管理,可在请求内存时找到合适的空闲内存分配。空闲内存的分割会产生内存碎片,合并内存可以缓解内存碎片问题。在空闲链表上搜索合适的空闲块有不同的策略:首次适配,下一次适配,最佳适配。
优缺点对比:
策略 利用率 查找效率
首次适配 高 底
下一次适配 低 高
最佳适配 最高 最低
简单的隐式空闲链表和双向空闲链表查找空闲块都是线下关系的。使用分离的空闲链表,通过维护多个空闲链表,每个链表中的块的大致相等,避免对全部空闲块进行搜索,提高效率。
伙伴系统是其中的一个特例,每个链表中块的大小都是2的k次幂。分配时,递归二分块,每次讲剩下的半块(也叫伙伴)放到相应的空闲链表找那个。释放时,查找其伙伴是否空闲,如果空闲就合并,合并后继续合并,知道某个遇到一个已分配的伙伴时,停止合并。(快速搜索和快速合并,可能导致显著的内存碎片)
网友评论