• 物理内存管理


      Linux内核管理物理内存是通过分页机制实现的,它将整个内存划分成无数个4k(在i386体系结构中)大小的页,从而分配和回收内存的基本单位便是内存页了。系统在分配内存时不再要求大块的连续内存,但是实际上系统使用内存时还是倾向于分配连续的内存块。为了尽量减少不连续情况,内核采用了“伙伴”关系来管理空闲页面。

      Linux的伙伴算法把所有的空闲页面分为10个块组,每组中块的大小是2的幂次方个页面,即第0组中块的大小都为20(1个页面),第9组中块的大小都为29(512个页面)。也就是说每一组中块的大小是相同的,且这些同样大小的快形成一个链表。以下例子展示该算法的工作过程:

      假设要求分配的块大小为128个页面。该算法现在块大小为128个页面的链表中查找,看是否有这样一个空闲块。如果有就直接分配,否则查找下一个更大的块,也就是在块大小为256个页面的链表中查找一个空闲块。如果存在这样的空闲块,内核就把这256个页面分为两等份,一份分配出去,另一份插入到块大小为128个页面的链表中。如果在块大小为256个页面的链表中也没有空闲页块,就继续找更大的块(512个页面的块)。如果存在,内核就从512个页面的块中分出128个页面满足请求,然后从384个页面中取出256个页面插入到块大小为256个页面的链表中,把剩下的128个页面插入到块大小为128个页面的链表中。如果连512个页面的链表中也没有空闲块,则放弃分配,返回错误信息。

      以上过程的逆过程就是块的释放过程,满足以下条件的两个块称为伙伴:1.两个块大小相同;2.两个块物理地址连续。伙伴算法把满足以上条件的两个快合并为一个块。而且该算法是迭代的,如果合并后的块还存在伙伴,则继续合并。

      内核中分配空闲页面的基本函数时get_free_page/get_free_pages,用于分配单页或者指定的页面数。get_free_pages实在内核中分配内存,而malloc实在用户空间中分配。malloc在用户空间分配内存可以以字节为单位分配,但内核在内部仍然以页为单位分配。

      

    Slab

      内核常常会使用到圆圆小于一页的内存块,而且这些小块内存频繁地生成和销毁。为了满足内核对小内存块的需要,Linux采用了一种称为slab分配器的技术。核心思想是“存储池”的运用。内存片段被看作对象,当被使用完后,并不直接释放而是被缓存到“存储池”中,以供下次使用。Slab并不是脱离伙伴关系而独立存在的一种内存分配方式,仍然是建立在页面基础上,它将来自伙伴关系管理的页面分割成众多小内存块以供使用。

    Kmalloc

      Kmalloc是Slab分配器提供的借口,用于完成内核程序中对小于一页的小块内存的请求。

    Vmalloc

      伙伴关系只是减轻了外部分片(所谓外部分片是指系统虽然有足够的内存,但却是分散的碎片,无法满足对大块“连续内存”的需求)的危害,但并未彻底消除。

      解决的思路时利用不连续的内存块组成“看起来很大的内存块”,类似于用户空间分配虚拟内存,内存逻辑上连续,其实映射到并不一定连续的物理内存上。内核提供vmalloc函数分配内核虚拟内存。

  • 相关阅读:
    ThreadLocal的原理和使用场景
    sleep wait yield join方法的区别
    GC如何判断对象可以被回收
    双亲委派
    ConcurrentHashMap原理,jdk7和jdk8版本
    hashCode和equals
    接口和抽象类区别
    为什么局部内部类和匿名内部类只能访问局部final变量
    【GAN】基础GAN代码解析
    TF相关codna常用命令整理
  • 原文地址:https://www.cnblogs.com/yitong0768/p/4658367.html
Copyright © 2020-2023  润新知