zoukankan      html  css  js  c++  java
  • Linux kmalloc/kfree 源码解读

    kmalloc/kfree用于划分和回收内核空间低区内存的方法。改组方法没有直接通过伙伴系统进行内存的划分,通过slab算法进行分配的。同时也为每个CPU提供一个阵列缓存,用于提高分配效率。下面对改组函数进行源码级的分析。

    内存分配

    static inline void *kmalloc(size_t size, gfp_t flags)

    1.         Slab通用缓存中查找可用的缓存(可以分配的)

           cachep = __find_general_cachep(size, flags);

           if (unlikely(cachep == NULL))

                  return NULL;

           如果没找到可用的缓存,直接返回0,表示分配失败。

    2.         接着,就从缓存中分配Slab对象。先从CPU的阵列缓存中申请对象。如果缓存中还有Slab对象。

           ac = cpu_cache_get(cachep);

           if (likely(ac->avail)) {

                  STATS_INC_ALLOCHIT(cachep);

                  ac->touched = 1;

                  objp = ac->entry[--ac->avail];

           }

    3.         如果阵列缓存中没有对象,则需要向Slab缓存申请对象,重填阵列缓存,然后再分配对象。

    a)         首先尝试从节点的共享缓存中进行分配。

           if (l3->shared) {

                  struct array_cache *shared_array = l3->shared;

                  if (shared_array->avail) {

                         if (batchcount > shared_array->avail)

                                batchcount = shared_array->avail;

                         shared_array->avail -= batchcount;

                         ac->avail = batchcount;

                         memcpy(ac->entry,

                                &(shared_array->entry[shared_array->avail]),

                                sizeof(void *) * batchcount);

                         shared_array->touched = 1;

                         // 分配成功

                         goto alloc_done;

                  }

           }

    b)        接着判断Slab缓存是不是空了,如果空了就需要为缓存注入新的血液。我们知道Slab缓存中有3个链表,分别指向全满,半满和全空的Slab。通过判断这三个链表是不是为空,来决定要不要向伙伴系统申请Slab缓存。

                  entry = l3->slabs_partial.next;

                  if (entry == &l3->slabs_partial) {

                         l3->free_touched = 1;

                         entry = l3->slabs_free.next;

                         if (entry == &l3->slabs_free)

                                goto must_grow;

                  }

    c)        如果缓存中仍然存在可用的Slab对象,则分配,填充阵列缓存。

                  while (slabp->inuse < cachep->num && batchcount--) {

                         ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,

                                                         numa_node_id());

                  }

    d)        如果发现Slab缓存中的对象都已经分配完了,需要从伙伴系统中申请Slab对象,来增长缓存。

           if (unlikely(!ac->avail)) {

                  int x;

                  x = cache_grow(cachep, flags, numa_node_id());

     

                  // cache_grow can reenable interrupts, then ac could change.

                  ac = cpu_cache_get(cachep);

                  if (!x && ac->avail == 0)      // no objects in sight? abort

                         return NULL;

     

                  if (!ac->avail)  // objects refilled by interrupt?

                         goto retry;

           }

     

    kfree函数很简单,将Slab对象释放到阵列缓存中,如果缓存满了,则批量释放到Slab缓存中

  • 相关阅读:
    常见数据结构和算法 的可视化
    JSON与XML
    JavaScript 中的陷阱
    C++ primer(十三)--类继承、构造函数成员初始化、虚函数、抽象基类
    mongodb学习(二)
    再谈怎样以最简单的方法将泛型为String类型的集合或String类型的数组转化为逗号间隔字符串形式
    LaTeX Subfigure 中间加入垂直线
    JAVA基础针对自己薄弱环节总结02(循环)
    软考之路--用文字记录这个漂亮的进程
    mysql异常Lock wait timeout exceeded; try restarting transaction
  • 原文地址:https://www.cnblogs.com/Ph-one/p/4414836.html
Copyright © 2011-2022 走看看