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缓存中

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。