内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)
生活随笔
收集整理的這篇文章主要介紹了
内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
我們知道kmem_cache中對于每CPU都有一個array_cache,已作為每CPU申請內存的緩存.? 此函數(shù)的目的在于:每個kmem_cache都有一個kmem_list3實例,該實例的shared作為一個kmem_cache上所有CPU的內存申請緩存.? 但是在此之前,seup_cpu_cache中對于kmem_cache中array_cache的值初始化體現(xiàn)不出緩存思想,而且對于kmem_cache中的kmem_list3.shared也沒有利用.
kmem_cache_init_late的目的就在于完善slab分配器的緩存機制.???????????????????????????????????????????????????????????????????????????? ?
|-->page_address_init()||-->setup_arch(&command_line);||-->setup_per_cpu_areas();||-->build_all_zonelist()||-->page_alloc_init()||-->pidhash_init()||-->vfs_caches_init_early()||-->mm_init()||-->.......||-->gfp_allowed_mask = __GFP_BITS_MASK;| 在此之前,gfp_allowed_mask = GFP_BOOT_MASK;||-->kmem_cache_init_late();|
?
?
void __init kmem_cache_init_late(void)|-->struct kmem_cache *cachep;||-->list_for_each_entry(cachep, &cache_chain, next)|-->if (enable_cpucache(cachep, GFP_NOWAIT)) BUG();||--g_cpucache_up = FULL;||-->init_lock_keys();||-->register_cpu_notifiler(&cpu_notifier);?
?
int enabel_cpucache(struct kmem_cache *cachep, gfp_t gfp)|-->int limit;||-->if (cachep->buffer_size > 131072) limit = 1;| else if (cachep->buffer_size > PAGE_SIZE) limit = 8;| else if (cachep->buffer_size > 1024) limit = 24;| else if (cachep->buffer_size > 256) limit = 54;| else limit = 120;| 為什么選擇這些數(shù)值啊,不明白???||-->int shared = 0;| if(cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1)| shared = 8;||--int err = 0;| err = do_tune_cpucache(cachep, limit, (limit + 1) / 2, shared, gfp);||--return err;?
?
int do_tune_cpucache(struct kmem_cache *cachep, int limit,int batchcount, int shared, gfp_t gfp)|-->struct ccupdate_struct *new = NULL;| new = kazlloc(sizeof(*new), gfp);||--int i;|--for_each_online_cpu(i)|--{| new->new[i] = alloc_arraycache(cpu_to_node(i), limit,| batchcount, gfp);| 根據(jù)limit, batchcount數(shù)值,構建新的array_cache實例.|| 因為kmem_cache中的array_cache是每個CPU的,所以此處是循環(huán),為每個CPU都| 都構建一個array_cache實例.|--}||-->new->cachep = cachep;||-->on_each_cpu(do_ccupdate_local, (void*)new, 1);| 將kmem_cache下的每個CPU的array_cache[i]更換成new->new[i];||-->cachep->batchcount = batchcount;| cachep->limit = limit;| cachep->shared = shared;||| 上面以替換了kmem_cache下的每個CPU的array_cache[i],
| 因此需要把原來的array_cache釋放掉.|--for_each_online_cpu(i)|--{| struct array_cache *ccolde = new->new[i];| if(!ccold) continue;|| free_block(cachep, ccold->entry, ccold->avail, cpu_to_node(i));| 我們知道在此之前,ccold->avail一直為0,所以該函數(shù)暫時可以不看.| 此函數(shù),就是把ccold->avail個ccole->entry中的數(shù)組元素指向的內存空間| 釋放給slab管理器.||| kfree(ccold);| 基本同于free_block,我們知道slab所管理的內存都是位于低端內存,低端內存的物| 理地址及其對應的虛擬地址存在固定偏移,因此根據(jù)該部分的虛擬地址可以很容易的找到| struct page實例,而struct page中的lru鏈表,在slab中被復用了,根據(jù)鏈表| 指針可以找到kmem_cache實例,所以kfree基本等同于free_block;| 但是kfree與free_block的重要的不同點在于,free_block直接將內存釋放給了| slab管理器,而kfree首選將內存釋放給每CPU的array_cache數(shù)組.||--}|-->kfree(new);||--return alloc_kmemlist(cachep, gfp);| 每個kmem_cache中的kmem_list3.shared上array_cache可以被所有CPU共享.
?
?
我們知道kmem_cache中對于每CPU都有一個array_cache,已作為每CPU申請內存的緩存. 此函數(shù)的目的在于:每個kmem_cache都有一個kmem_list3實例,該實例的shared作為 一個kmem_cache上所有CPU的內存申請緩存(對于UMA,kmem_cache.alien沒有用處). 此時,我們不妨猜測,當一個CPU通過kmalloc申請內內存時,將從kmem_cache實例上 自己的array_cache進行申請,如果沒有則從kmem_list3->shared上補充到array_cache上, 如果kmem_list3上也每有,將從slab管理器上獲取,充分體現(xiàn)了緩存的利用. int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp)|-->int node = 0;| struct kmem_list3 *l3 = NULL;| struct array_cache *new_shared = NULL;| struct array_cache **new_alien = NULL;||-->for_each_online_node(node)|--{| new_shared = NULL;| if(cachep->shared)| new_shared = alloc_arraycache(node, | cachep->shared * cachep->batchcount,| 0xbaadf00d, gfp);||| l3 = cachep->nodelists[node];| if(l3)| |-{| | struct array_cache *shared = l3->shared;| | if(shared)| | free_block(cachep, shared->entry, shared->avail, node);| | l3->shared = new_shared;| | if(!l3->alien) l3->alien = new_alien, new_alien = NULL;| | l3->free_limit = (1 + NR_CPUS) * cachep->batchcount
| | + cachep->num;| | kfree(shared);| | free_alien_cache(new_alien);| | continue; //對于單節(jié)點,再次continue時,將退出循環(huán)| |-}| || || ...... 對于UMA體系 nothing| |
|--}
||--return 0;
?
?
void do_ccupdate_local(void *info)|-->struct ccupdate_struct *new = info;| struct array_cache *old = cpu_cache_get(new->cachep);||-->new->cachep->array[smp_processor_id()] =| new->new[smp_processor_id];
| new->new[smp_processor_id()] = old;
?
?
struct array_cache *alloc_arraycache(int node, int entries,int batchcount, gfp_t gfp)|-->int memsize = sizeof(void *) * entries| + sizeof(struct array_cache);
| 根據(jù)entries的數(shù)值,計算該分配的array_cache空間大小.||-->struct array_cache *nc = NULL;| nc = kmalloc_node(memsize, gfp, node);| nc->avail = 0;| nc->limit = entries;| nc->batchcount = batchcount;| nc->touched = 0;| spin_lock_init(&nc->lock);||-->return nc;
?
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle ABP(Autotask
- 下一篇: 计算机网络基础(路由原理)