日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

内存管理 初始化(七)kmem_cache_init_late 初始化slab分配器(下)

發(fā)布時(shí)間:2025/7/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内存管理 初始化(七)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ī)制.???????????????????????????????????????????????????????????????????????????? ?

start_kernel()
|-->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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。