Chinaunix首页 | 论坛 | 博客
  • 博客访问: 286092
  • 博文数量: 60
  • 博客积分: 2697
  • 博客等级: 少校
  • 技术积分: 653
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-13 15:52
文章分类

全部博文(60)

文章存档

2012年(6)

2011年(31)

2010年(23)

分类: LINUX

2011-03-15 13:21:45

/**
* kmem_cache_destroy - delete a cache
* @cachep: the cache to destroy
*
* Remove a struct kmem_cache object from the slab cache.
*
* It is expected this function will be called by a module when it is
* unloaded.  This will remove the cache completely, and avoid a duplicate
* cache being allocated each time a module is loaded and unloaded, if the
* module doesn’t have persistent in-kernel storage across loads and unloads.
*
* The cache must be empty before calling this function.
*
* The caller must guarantee that noone will allocate memory from the cache
* during the kmem_cache_destroy().
*/
void kmem_cache_destroy(struct kmem_cache *cachep)
{
BUG_ON(!cachep || in_interrupt());
/* Don’t let CPUs to come and go */
lock_cpu_hotplug();
/* Find the cache in the chain of caches. */
mutex_lock(&cache_chain_mutex);
/*
  * the chain is never empty, cache_cache is never destroyed
  */
// cache的第一个元素cache_cache是静态量,该链表永远不会空
// 从cache链表中删除cache
list_del(&cachep->next);
mutex_unlock(&cache_chain_mutex);
// 尽可能释放cache中的slab单元块
if (__cache_shrink(cachep)) {
  slab_error(cachep, "Can’t free all objects");
  mutex_lock(&cache_chain_mutex);
  list_add(&cachep->next, &cache_chain);
  mutex_unlock(&cache_chain_mutex);
  unlock_cpu_hotplug();
  return;
}
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
  synchronize_rcu();
// 释放cache
__kmem_cache_destroy(cachep);
unlock_cpu_hotplug();
}


EXPORT_SYMBOL(kmem_cache_destroy);


// 真正的摧毁cache函数
static void __kmem_cache_destroy(struct kmem_cache *cachep)
{
int i;
struct kmem_list3 *l3;
// 释放cache中所有CPU的数组
for_each_online_cpu(i)
     kfree(cachep->array);
/* NUMA: free the list3 structures */
// 释放list3中的所有内存
for_each_online_node(i) {
  l3 = cachep->nodelists;
  if (l3) {
   kfree(l3->shared);
   free_alien_cache(l3->alien);
   kfree(l3);
  }
}
// 释放cache本身
kmem_cache_free(&cache_cache, cachep);
}

/*
* kmem_cache_shrink - Shrink a cache.
* @cachep: The cache to shrink.
*
* Releases as many slabs as possible for a cache.
* To help debugging, a zero exit status indicates all slabs were released.
*/

//该函数尽可能地释放cache中的slab块, 当cache空闲空间太多时会释放掉一些内存供其他内核部分使
用.
int kmem_cache_shrink(struct kmem_cache *cachep)
{
BUG_ON(!cachep || in_interrupt());
return __cache_shrink(cachep);
}


EXPORT_SYMBOL(kmem_cache_shrink);

static int __cache_shrink(struct kmem_cache *cachep)
{
int ret = 0, i = 0;
struct kmem_list3 *l3;
// 释放cache中每个CPU对应的空间
drain_cpu_caches(cachep);
check_irq_on();
for_each_online_node(i) {
// 释放每个节点的list3
  l3 = cachep->nodelists;
  if (!l3)
   continue;
// 将slab从slab_free中释放
  drain_freelist(cachep, l3, l3->free_objects);
  ret += !list_empty(&l3->slabs_full) ||
   !list_empty(&l3->slabs_partial);
}
return (ret ? 1 : 0);
}


static void drain_cpu_caches(struct kmem_cache *cachep)
{
struct kmem_list3 *l3;
int node;
on_each_cpu(do_drain, cachep, 1, 1);
check_irq_on();
for_each_online_node(node) {
  l3 = cachep->nodelists[node];
  if (l3 && l3->alien)
// 释放cache的list3的alien部分
   drain_alien_cache(cachep, l3->alien);
}
for_each_online_node(node) {
  l3 = cachep->nodelists[node];
  if (l3)
// 释放list3的数组空间
   drain_array(cachep, l3, l3->shared, 1, node);
}
}


/*
* Remove slabs from the list of free slabs.
* Specify the number of slabs to drain in tofree.
*
* Returns the actual number of slabs released.
*/
static int drain_freelist(struct kmem_cache *cache,
   struct kmem_list3 *l3, int tofree)
{
struct list_head *p;
int nr_freed;
struct slab *slabp;
nr_freed = 0;
// 从slabs_free链表释放
while (nr_freed slabs_free)) {
  spin_lock_irq(&l3->list_lock);
  p = l3->slabs_free.prev;
  if (p == &l3->slabs_free) {
   spin_unlock_irq(&l3->list_lock);
   goto out;
  }
// 获取slab
  slabp = list_entry(p, struct slab, list);
#if DEBUG
  BUG_ON(slabp->inuse);
#endif
// 将slab从链表中删除
  list_del(&slabp->list);
  /*
   * Safe to drop the lock. The slab is no longer linked
   * to the cache.
   */
// 空闲对象数减少一个slab中的对象数
  l3->free_objects -= cache->num;
  spin_unlock_irq(&l3->list_lock);
// 释放slab
  slab_destroy(cache, slabp);
  nr_freed++;
}
out:
return nr_freed;
}

/* include/linux/slab.h */
// 注意kmalloc是在头文件中定义的
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size)) {
// 以下是找一个对象大小刚好大于等于size的cache
  int i = 0;
#define CACHE(x) \
  if (size
// 这是kmalloc_sizes.h文件内容, 实际就是定义CACHE中可用的对象大小
// 普通情况下最大是128K, 也就是kmalloc能分配的最大内存量
#if (PAGE_SIZE == 4096)
CACHE(32)
#endif
CACHE(64)
#if L1_CACHE_BYTES  512) || (MAX_NUMNODES > 256) || !defined(CONFIG_MMU)
CACHE(262144)
#endif
#ifndef CONFIG_MMU
CACHE(524288)
CACHE(1048576)
#ifdef CONFIG_LARGE_ALLOCS
CACHE(2097152)
CACHE(4194304)
CACHE(8388608)
CACHE(16777216)
CACHE(33554432)
#endif /* CONFIG_LARGE_ALLOCS */
#endif /* CONFIG_MMU
/* mm/slab.c */
// kfree实际也是调用__cache_free来释放空间


void kfree(const void *objp)
{
struct kmem_cache *c;
unsigned long flags;
if (unlikely(!objp))
  return;
local_irq_save(flags);
kfree_debugcheck(objp);
c = virt_to_cache(objp);
debug_check_no_locks_freed(objp, obj_size(c));
__cache_free(c, (void *)objp);
local_irq_restore(flags);
}
EXPORT_SYMBOL(kfree);

阅读(1112) | 评论(0) | 转发(0) |
0

上一篇:kmem_cache_create()解析

下一篇:Vi编辑器

给主人留下些什么吧!~~