ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:21.41KB ,
资源ID:19010988      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/19010988.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(slab源码分析销毁函数文档格式.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

slab源码分析销毁函数文档格式.docx

1、entryac-avail+ = objp; else /这是本地缓存空闲对象大于上限的情况,先调整本地缓存 STATS_INC_FREEMISS(cachep); cache_flusharray(cachep, ac); /不过之后还是要把该对象释放给本地缓存 再看cache_flusharray()函数:static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) int batchcount; struct kmem_list3 *l3; int node = numa_node_id()

2、; /本地缓存能一次转出多少个对象,这个是之前规定的 batchcount = ac-batchcount;#if DEBUG BUG_ON(!batchcount | batchcount avail);#endif /获得此缓存器的三链 l3 = cachep-nodelistsnode; spin_lock(&l3-list_lock); /看是否存在本地共享缓存 if (l3-shared) struct array_cache *shared_array = l3-shared; /本地 共享 缓存还可承载的最大数目 int max = shared_array-limit - sh

3、ared_array-avail; if (max) /最大只能为max if (batchcount max) batchcount = max; /将本地缓存前面的几个对象转入本地共享缓存中,因为前面的是最早不用的 memcpy(&(shared_array-entryshared_array-avail),entry, sizeof(void *) * batchcount); /更新本地共享缓存 shared_array-avail += batchcount; goto free_done; /没有配置本地共享缓存,只能释放对象到三链中 /注意此时的 batchcount 就是原始的

4、 batchcount,也就是说可以把达到本地缓存一次性转出 batchcount 的目标 /而上面的本地共享缓存如果使用的话,有可能达不到这个目标,因为它也有 limit /不过即便达不到,由于本地共享缓存效率比三链高,这种情况也不会在到三链来,而是直接goto free_done。 free_block(cachep, ac-entry, batchcount, node);free_done:#if STATS /.DEBUG spin_unlock(& /更新本地缓存的情况avail -= batchcount; /把后面的移动到本地缓存数组前面来 memmove(ac-entry,

5、&(ac-entrybatchcount), sizeof(void *)*ac-如果没有本地共享缓存,或者本地共享缓存达到limit了,那就把该对象回收到三链中: * Caller needs to acquire correct kmem_lists list_lock */ /释放一定数目的对象static void free_block(struct kmem_cache *cachep, void *objpp, int nr_objects, int node) int i; /逐一释放对象到三链中 for (i = 0; i list); check_spinlock_acqui

6、red_node(cachep, node); check_slabp(cachep, slabp); /将对象放到其 slab 中 slab_put_obj(cachep, slabp, objp, node); STATS_DEC_ACTIVE(cachep); /增加空闲对象计数 l3-free_objects+; /* fixup slab chains */ /如果slab中全都是空闲对象 if (slabp-inuse = 0) /如果三链中空闲对象数目超过上限,直接回收整个 slab 到内存,空闲对象数减去每个slab中对象数free_objects free_limit) fr

7、ee_objects -= cachep-num; /* No need to drop any previously held * lock here, even if we have a off-slab slab * descriptor it is guaranteed to come from * a different cache, refer to comments before * alloc_slabmgmt. */ /销毁slab对象 slab_destroy(cachep, slabp); else /到这里说明空闲对象数目还没有超过三链设置的上限 /只需将此slab添加

8、到空slab链表中 list_add(&list, &slabs_free); /* Unconditionally move a slab to the end of the * partial list on free - maximum time for the * other objects to be freed, too. /将此slab添加到部分满的链表中 list_add_tail(&slabs_partial);整个流程就是这样,回收优先级:本地缓存本地共享缓存三链。销毁slab销毁slab就是释放slab管理区和对象占用的空间,还给伙伴系统。* * slab_destroy

9、 - destroy and release all objects in a slab * cachep: cache pointer being destroyed * slabp: slab pointer being destroyed * * Destroy all the objs in a slab, and release the mem back to the system. * Before calling the slab must have been unlinked from the cache. The * cache-lock is not held/needed

10、. /销毁slab,需要释放管理对象和slab对象static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp) /获得slab页面的首地址,是用第一个对象的地址colouroff(对于内置式slab,colouroff已经将slab管理者包括在内了) void *addr = slabp-s_mem - slabp-colouroff; /debug用 slab_destroy_objs(cachep, slabp); /使用SLAB_DESTROY_BY_RCU来创建的高速缓存 if (unlikely(cac

11、hep-flags & SLAB_DESTROY_BY_RCU) /rcu方式释放,暂时不做分析,主要是做并行优化 struct slab_rcu *slab_rcu; slab_rcu = (struct slab_rcu *)slabp; slab_rcu-cachep = cachep;addr = addr; /注册一个回调来延期释放slab call_rcu(&slab_rcu-head, kmem_rcu_free); /释放slab占用的页面到伙伴系统中 /如果是内置式,slab管理者和slab对象在一起,可以同时释放 kmem_freepages(cachep, addr);

12、if (OFF_SLAB(cachep) /外置式,还需释放slab管理对象 kmem_cache_free(cachep-slabp_cache, slabp);与伙伴系统交互的函数暂不再本文讨论范围之内。销毁缓存器销毁缓存器首先要保证的一点就是当前缓存器中所有的对象都是空闲的,也就是之前分配出去的对象都已经释放回来了,其主要的步骤如下:将缓存器 kmem_cache 从 cache_chain 链表中删除。将本地高速缓存,align高速缓存和本地共享缓存中的对象都回收到slab三链,并释放所有的free链表,然后判断full链表以及partial链表是否都为空,如果有一个不为空说明存在非空

13、闲slab,也就是说*还有对象未释放,此时无法销毁缓存器,必须重新将缓存器添加到 cache_chain 链表中。确定所有的对象都为空闲状态后,将缓存器涉及到的所有描述符都释放(这些描述符都是保存在通用缓存器中的,如slab管理者)。负责销毁缓存器的函数为kmem_cache_destroy():/* * kmem_cache_destroy - delete a cache the cache to destroy * Remove a &struct kmem_cache object from the slab cache. * It is expected this function

14、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 doesnt have persistent in-kernel storage across loads and unloads. * The cache must be empty before callin

15、g this function. * The caller must guarantee that noone will allocate memory from the cache * during the kmem_cache_destroy(). /销毁一个缓存器,通常这只发生在卸载module时void kmem_cache_destroy(struct kmem_cache *cachep)cachep | in_interrupt(); /* Find the cache in the chain of caches. */ mutex_lock(&cache_chain_mute

16、x); /* * the chain is never empty, cache_cache is never destroyed /将缓存器从cache_chain的链表中摘除cachep-next); if (_cache_shrink(cachep) /释放空链表中的slab,并检查其他两个链表。在销毁缓存器前,必须先销毁其中的slab /满slab链或部分满slab链不为空 slab_error(cachep, Cant free all objects); /缓存器非空,不能销毁,重新加入到cache_chain链表中next, &cache_chain); mutex_unlock

17、(& /有关rcu SLAB_DESTROY_BY_RCU) synchronize_rcu(); /底层调用_kmem_cache_destroy()函数来实现 _kmem_cache_destroy(cachep);释放空链表的slab由下面这个函数负责:/* Called with cache_chain_mutex held to protect against cpu hotplug */释放空链表中的slabstatic int _cache_shrink(struct kmem_cache *cachep) int ret = 0, i = 0; /释放本地缓存中对象 drain

18、_cpu_caches(cachep); check_irq_on(); for_each_online_node(i) nodelistsi; if (!l3) continue; /释放空链表中的slab drain_freelist(cachep, l3, l3-free_objects); /检查满slab链表和部分满slab链表是否还有slab ret += !list_empty(&slabs_full) | ! return (ret ? 1 : 0);其中用到了这几个函数:/释放本地缓存和本地共享缓存中的对象static void drain_cpu_caches(struct

19、 kmem_cache *cachep) int node; /释放每个本地缓存中的对象,注意没有 online on_each_cpu(do_drain, cachep, 1, 1); /调用了do_drain()函数 /NUMA相关,释放每个NUMA节点的alien for_each_online_node(node) if (l3 &alien) /本版本目前是空函数,暂不支持 drain_alien_cache(cachep, l3-alien); /释放本地共享缓存中的对象 if (l3) drain_array(cachep, l3, l3-shared, 1, node);/释放

20、本地缓存中的对象static void do_drain(void *arg) struct kmem_cache *cachep = arg; struct array_cache *ac; /获得本地缓存 ac = cpu_cache_get(cachep);nodelistsnode- /释放本地缓存中的对象entry, ac-avail, node);avail = 0; * Drain an array if it contains any elements taking the l3 lock only if * necessary. Note that the l3 listlo

21、ck also protects the array_cache * if drain_array() is sed on the shared array.void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3, struct array_cache *ac, int force, int node) int tofree;ac | !ac-avail) if (ac-touched &force) touched = 0; spin_lock_irq(&avail) /计算释放对象的数目,可见这个函数还支持部分释放,取决于force的bool属性 /从 drain_cpu_caches()进入时,force=1,是要全部释放的 tofree = force ?avail : (ac-limit + 4) / 5; if (tofree tofree = (ac-avail + 1) / 2; /释放对象,从entry前面开始entry, tofree, node);avail -= tofree; /后面的对象前移entrytofree), sizeof(void *) * ac- spin_unlock_irq(&drain_array()函数是把本地缓存和本地共享缓存释放到三链中,所以会用到:

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1