linux减小高速缓存,Linux 高速缓存的释放

/**

* 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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值