内核内存的分配

当用户态进程需要额外内存的时候,可以从内核所维护的空闲页帧链表中获取页,该链表通常由页替换算法来更新,这些页帧通常分散在物理内存当中,如果用户只需要一个字节的内存,那么会产生内存碎片,这是因为进程会得到整个页帧

内核内存的分配通常是从空闲内存池中获取的,而并不是从满足普通用户模式进程的内存链表中获取的,主要有两个原因

  • 1、内核需要为不同大小的数据结构分配内存,其中有的不到一页,因此内核必须谨慎使用内存,并视图降低碎片浪费,这一点是十分重要的,因为很多操作系统的内核代码和数据不受分页系统控制
  • 2、用户进程所分配的页不必要在连续的物理内存当中,但是有的硬件需要直接与物理内存打交道,而不需要经过虚拟内存接口,因此需要内存常驻在连续内存页中,而一般与硬件通信都是内核做的事情,所以它不是从满足普通用户模式进程的内存链表中获取

Linux原来使用的是Buddy系统来分配内核内存的

Buddy系统从物理连续的大小固定的段上进行分配。内存按2的幂的大小来进行分配,就比如说4KB、8KB、16KB等。如果请求大小不为2的幂,那么需要调整到下一个更大的2的幂,就比如说请求大小为11KB,那么就会按照16KB来请求,这样的话就会造成空间的浪费

所以Linux的内核版本从2.2开始使用slab分配器

slab是一个或多个物理上的连续的页的组成的,每个内核数据结构都有一个cache,比如说进程描述符、文件对象、信号量等,每个cache都含有内核数据结构的对象实例,就比如说信号量cache存储着信号量对象,进程描述符cache存放着进程描述符对象,而每个cache都是由若干个slab组成的,而每个slab又分为若干个与对象大小相同的部分,所以当内核请求对象内存的时候,slab分配器可以返回刚好可以表示对象的所需的内存

这里写图片描述

当创建cache的时候,起初包含了若干标记为空闲的对象,对象的数量与slab的大小有关,开始,所有的对象都标记为空闲。当需要内核数据结构的对象时,可以从cache上直接获取,并将该对象标记为使用

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

Linux的slab可有三种状态:

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

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

当内核请求对象内存的时候,slab分配器可以返回刚好表示对象的所需的内存,slab分配器对于经常需要不断分配内存、释放内存来说特别有效,因为对象预先创建,所以可以从cache上快速分配,另外,当用完对象释放的时候,只需要标记为空闲并且返回给cache,以便下次调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值