Linux 内存管理

0.内存碎片

  • 外部内存碎片,也就是产生了多个不连续的小物理内存,导致新的程序无法被装载;
  • 内部内存碎片,程序所有的内存都被装载到了物理内存,但是这个程序有部分的内存可能并不是很常使用,这也会导致内存的浪费;

1.Linux内存管理

内核空间申请内存:

kmalloc/free->slab->buddy

用户空间申请内存:

malloc/free->brk ,sbrk, mmap->buddy

2.buddy伙伴算法

以页为请求单位(4096 byte),将空闲内存拆分成11个链表,每个链表中每块大小分别是 2^n * 4k大小(n为链表索引)。当请求一个 3页的内存时,在索引为3的链表中查找,找到返回,如果没找到继续到"更大块"的链表中查找,找到后从更大快中查出一块用于返回,剩下的拆分成小块 加入链表中。 释放就是一个合并块小块为大块。

很多时候再用户层实现自己的内存管理模块,是因为即使请求的是1byte内存,实际分配的物理内存是1页(4096byte),产生内部内存碎片

3.malloc free

clip_image004

mmap 和brk是分配逻辑地址内存不是真正的物理内存,当第一次操作内存引起缺页时使用buddy算法分配内存。

malloc小于128k的内存,使用brk分配内存。直接改变edata。

malloc大于128k的内存,使用mmap分配内存。在空闲链表中找到一块可用的内存(first fit ,best fit,worst fit)。

malloc 会对内存进行整理(拆分 合并)

4.slab

img

高速缓存的内存区被划分为多个slab,每个slab由一个或多个连续的页框组成,这些页框中既包含已分配的对象,也包含空闲的对象。

下面考虑内核如何将slab分配给表示进程描述符的对象。在Linux系统中,进程描述符的类型是struct task_struct ,其大小约为1.7KB。当Linux 内核创建新任务时,它会从cache 中获得struct task_struct 对象所需要的内存。Cache 上会有已分配好的并标记为空闲的struct task_struct 对象来满足请求。

Linux 的slab 可有三种状态:

  • 满的:slab 中的所有对象被标记为使用。
  • 空的:slab 中的所有对象被标记为空闲。
  • 部分:slab 中的对象有的被标记为使用,有的被标记为空闲。

slab 分配器首先从部分空闲的slab 进行分配。如有,则从空的slab 进行分配。如没有,则从物理连续页上分配新的slab,并把它赋给一个cache ,然后再从新slab 分配空间

百度百科

总结

buddy 解决了外部内存碎片问题,以页作为最小分配单位。

slab 内核分配算法,由于buddy最小分配单位为页,直接使用buddy分配小内存会导致内部内存碎片,所以引入slab。将缓存分为N个slab,slab分为M个页,每页分为K个固定大小的OBJ。(PS:好像就是个对象池)

malloc free 对虚拟内存的内存分配,真正的物理内存分配还是使用buddy。malloc对虚拟内存进行管理,但是并没有解决内部内存碎片问题。

参考文章

malloc:https://blog.csdn.net/songchuwang1868/article/details/89928421

slab:https://zhuanlan.zhihu.com/p/61457076

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值