分类: 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);