内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)
生活随笔
收集整理的這篇文章主要介紹了
内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
我們知道kmem_cache中對(duì)于每CPU都有一個(gè)array_cache,已作為每CPU申請(qǐng)內(nèi)存的緩存.? 此函數(shù)的目的在于:每個(gè)kmem_cache都有一個(gè)kmem_list3實(shí)例,該實(shí)例的shared作為一個(gè)kmem_cache上所有CPU的內(nèi)存申請(qǐng)緩存.? 但是在此之前,seup_cpu_cache中對(duì)于kmem_cache中array_cache的值初始化體現(xiàn)不出緩存思想,而且對(duì)于kmem_cache中的kmem_list3.shared也沒(méi)有利用.
kmem_cache_init_late的目的就在于完善slab分配器的緩存機(jī)制.???????????????????????????????????????????????????????????????????????????? ?
|-->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ù)值,構(gòu)建新的array_cache實(shí)例.|| 因?yàn)閗mem_cache中的array_cache是每個(gè)CPU的,所以此處是循環(huán),為每個(gè)CPU都| 都構(gòu)建一個(gè)array_cache實(shí)例.|--}||-->new->cachep = cachep;||-->on_each_cpu(do_ccupdate_local, (void*)new, 1);| 將kmem_cache下的每個(gè)CPU的array_cache[i]更換成new->new[i];||-->cachep->batchcount = batchcount;| cachep->limit = limit;| cachep->shared = shared;||| 上面以替換了kmem_cache下的每個(gè)CPU的array_cache[i],
| 因此需要把原來(lá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í)可以不看.| 此函數(shù),就是把ccold->avail個(gè)ccole->entry中的數(shù)組元素指向的內(nèi)存空間| 釋放給slab管理器.||| kfree(ccold);| 基本同于free_block,我們知道slab所管理的內(nèi)存都是位于低端內(nèi)存,低端內(nèi)存的物| 理地址及其對(duì)應(yīng)的虛擬地址存在固定偏移,因此根據(jù)該部分的虛擬地址可以很容易的找到| struct page實(shí)例,而struct page中的lru鏈表,在slab中被復(fù)用了,根據(jù)鏈表| 指針可以找到kmem_cache實(shí)例,所以kfree基本等同于free_block;| 但是kfree與free_block的重要的不同點(diǎn)在于,free_block直接將內(nèi)存釋放給了| slab管理器,而kfree首選將內(nèi)存釋放給每CPU的array_cache數(shù)組.||--}|-->kfree(new);||--return alloc_kmemlist(cachep, gfp);| 每個(gè)kmem_cache中的kmem_list3.shared上array_cache可以被所有CPU共享.
?
?
我們知道kmem_cache中對(duì)于每CPU都有一個(gè)array_cache,已作為每CPU申請(qǐng)內(nèi)存的緩存. 此函數(shù)的目的在于:每個(gè)kmem_cache都有一個(gè)kmem_list3實(shí)例,該實(shí)例的shared作為 一個(gè)kmem_cache上所有CPU的內(nèi)存申請(qǐng)緩存(對(duì)于UMA,kmem_cache.alien沒(méi)有用處). 此時(shí),我們不妨猜測(cè),當(dāng)一個(gè)CPU通過(guò)kmalloc申請(qǐng)內(nèi)內(nèi)存時(shí),將從kmem_cache實(shí)例上 自己的array_cache進(jìn)行申請(qǐng),如果沒(méi)有則從kmem_list3->shared上補(bǔ)充到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; //對(duì)于單節(jié)點(diǎn),再次continue時(shí),將退出循環(huán)| |-}| || || ...... 對(duì)于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ù)值,計(jì)算該分配的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ù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Oracle ABP(Autotask
- 下一篇: 计算机网络基础(路由原理)