销毁SLAB高速缓存kmem_cache_destroy()
作者:李万鹏 于北京 borqs
调用kmem_cache_destroy()释放cache。这个函数一般是在模块卸载的时候调用,在调用这个函数之前,cache应该是empty的。调用者必须保证在执行kmem_cache_destroy()的时候,不会对这个cache有任何内存分配。这里将share local slab中的指针释放回slab,然后对slabs_free上所有的slab进行释放。
int kmem_cache_destroy (kmem_cache_t * cachep)
{
int i;
/*指针不能为空,也不能在中断上下文*/
if (!cachep || in_interrupt())
BUG();
/* Don't let CPUs to come and go */
lock_cpu_hotplug();
/* Find the cache in the chain of caches. */
down(&cache_chain_sem);
/*将cache从cache_chain链表上删掉*/
list_del(&cachep->next);
up(&cache_chain_sem);
/*将slab中的对象都释放掉,如果slabs_partial或slabs_full链表不为空,则无法释放左右对象,再把cache加回以cache_chain为链表头的链表*/
if (__cache_shrink(cachep)) {
slab_error(cachep, "Can't free all objects");
down(&cache_chain_sem);
list_add(&cachep->next,&cache_chain);
up(&cache_chain_sem);
unlock_cpu_hotplug();
return 1;
}
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
synchronize_kernel();
/* no cpu_online check required here since we clear the percpu
* array on cpu offline and set this to NULL.
*/
/*释放cpu local slab 数组*/
for (i = 0; i < NR_CPUS; i++)
kfree(cachep->array[i]);
/* NUMA: free the list3 structures */
/*释放共享local cpu slab*/
kfree(cachep->lists.shared);
cachep->lists.shared = NULL;
/*释放cache的描述符*/
kmem_cache_free(&cache_cache, cachep);
unlock_cpu_hotplug();
return 0;
}
static int __cache_shrink(kmem_cache_t *cachep)
{
struct slab *slabp;
int ret;
/*将共享local slab上的对象全部释放回slab*/
drain_cpu_caches(cachep);
check_irq_on();
spin_lock_irq(&cachep->spinlock);
/*释放slabs_free上的所有对象,然后释放slab块*/
for(;;) {
struct list_head *p;
p = cachep->lists.slabs_free.prev;
if (p == &cachep->lists.slabs_free)
break;
slabp = list_entry(cachep->lists.slabs_free.prev, struct slab, list);
#if DEBUG
if (slabp->inuse)
BUG();
#endif
list_del(&slabp->list);
cachep->lists.free_objects -= cachep->num;
spin_unlock_irq(&cachep->spinlock);
slab_destroy(cachep, slabp);
spin_lock_irq(&cachep->spinlock);
}
ret = !list_empty(&cachep->lists.slabs_full) ||
!list_empty(&cachep->lists.slabs_partial);
spin_unlock_irq(&cachep->spinlock);
return ret;
}
static void drain_cpu_caches(kmem_cache_t *cachep)
{
smp_call_function_all_cpus(do_drain, cachep);
check_irq_on();
spin_lock_irq(&cachep->spinlock);
/*如果存在共享 local slab,将其释放回slab*/
if (cachep->lists.shared)
drain_array_locked(cachep, cachep->lists.shared, 1);
spin_unlock_irq(&cachep->spinlock);
}
static void drain_array_locked(kmem_cache_t *cachep,
struct array_cache *ac, int force)
{
int tofree;
check_spinlock_acquired(cachep);
if (ac->touched && !force) {
ac->touched = 0;
} else if (ac->avail) {
/*如果存在对象*/
tofree = force ? ac->avail : (ac->limit+4)/5;
if (tofree > ac->avail) {
tofree = (ac->avail+1)/2;
}
/*将对象归还给slab*/
free_block(cachep, ac_entry(ac), tofree);
ac->avail -= tofree;
memmove(&ac_entry(ac)[0], &ac_entry(ac)[tofree],
sizeof(void*)*ac->avail);
}
}
static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
{
int i;
check_spinlock_acquired(cachep);
/* NUMA: move add into loop */
/*要释放多少个对象,cache空闲对象的数目就增加多少*/
cachep->lists.free_objects += nr_objects;
for (i = 0; i < nr_objects; i++) {
void *objp = objpp[i];
struct slab *slabp;
unsigned int objnr;
/**获得对象坐在slab的地址/
slabp = GET_PAGE_SLAB(virt_to_page(objp));
/*把slab从它所在的链表上删除*/
list_del(&slabp->list);
/*计算对象的number*/
objnr = (objp - slabp->s_mem) / cachep->objsize;
check_slabp(cachep, slabp);
#if DEBUG
if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
printk(KERN_ERR "slab: double free detected in cache '%s', objp %p.\n",
cachep->name, objp);
BUG();
}
#endif
/*kmem_bufctl_t数组指向下一个空闲的对象*/
slab_bufctl(slabp)[objnr] = slabp->free;
slabp->free = objnr;
STATS_DEC_ACTIVE(cachep);
/*slab中对象的使用计数减一*/
slabp->inuse--;
check_slabp(cachep, slabp);
/*如果slab中没有正在使用的了*/
if (slabp->inuse == 0) {
/*如果cache的空闲对象大于cache空闲对象的上限*/
if (cachep->lists.free_objects > cachep->free_limit) {
/*从cache空闲对象的数目中减去这个slab中空闲对象的数目*/
cachep->lists.free_objects -= cachep->num;
/*撤销这个slab块*/
slab_destroy(cachep, slabp);
} else {
/*否则把这个slab添加到slabs_free链表上*/
list_add(&slabp->list,
&list3_data_ptr(cachep, objp)->slabs_free);
}
} else {
/* Unconditionally move a slab to the end of the
* partial list on free - maximum time for the
* other objects to be freed, too.
*/
/*如果还有正在使用的则把slab添加到slabs_partial链表上*/
list_add_tail(&slabp->list,
&list3_data_ptr(cachep, objp)->slabs_partial);
}
}
}
分享到:
相关推荐
Linux常见驱动源码分析(kernel hacker修炼之道)--李万鹏 李万鹏 IBM Linux Technology Center kernel team 驱动资料清单内容如下: Linux设备模型(中)之上层容器.pdf Linux设备模型(上)之底层模型.pdf Linux...
常见驱动源码分析( LINUX kernel hacker修炼之道)-李万鹏
常见驱动源码分析(kernel hacker修炼之道)
如果刚刚对linux的kernel有兴趣,想了解点什么的话,请先看看此书吧,她风趣幽默的介绍了linux的发展趣事,让你开心快乐之余慢慢领会linux的魅力,让你了解学习掌握kernel的方法。其中的很多建议经过我的实践和摸索...
2018年8月28日···网鼎杯-第三场-杂项-track_hacker
HackerRank-Interview-Preparation-Kit-master.rar
HackerRank---Linux-Shell-Problems_Solutions 问题可以通过 -
国嵌的笔记 非常的不容易 里面驱动 包括USB LCD 文件系统 内存管理有非常详细 的记录
[2-Hacker.HighSchool].HHS_en02_Windows_and_Linux
Linux PCI驱动牛人写的论文,有一定参考价值
HackerRank 2019-2018技能报告,报告中阐明 React, IOT和DeepLearning可能是互联网行业未来数年的最重要的发展方向.
This is the code for the hacker marathon held on June 27
骇客V1.0 描述 一个令人兴奋的游戏,将您带到了热门的位置,试图使MI6总部免遭破坏。 使用您的技能来克服这种情况。 记得保持冷静。 请下载并对其评分,以免错过。 即将推出进一步的升级! 更多信息 ...
有关hacker 的文章和资料分享给大家
super hacker tools pour tester beta
1. 报错回显 2. web中获取当前上下对象(response、context、writer等) 3. 可以出情况下OOB 1. 现状 2. 新的回显思路 3
processhacker-2.39 最新版高速下载
Cmake-3.22.0-linux-x86_64安装包
1. parse: Reads a set of *.java source files and maps the resulting token 2. ent
reverse-engineering-the-hacker-news-ranking-algorithm, 历史黑客新闻数据的分析与排序算法 反向工程黑客新闻排名算法这个知识库是文章反向工程的一个同伴,它黑客新闻排名算法。 本文探讨了如何利用历史数据来...