新四季網

內存初始化模式怎麼選(內存管理14zone初始化2)

2023-10-29 14:11:27 2

內存管理(13)zone初始化1中說到free_area_init_node函數,接下來主要做的工作如下:

1.計算有效頁框數,總頁框數

2.初始化內存節點管理數據結構pgdat

2.初始化zone管理數據結構其中包含空閒鍊表

3.初始化zone下的管理的頁框屬性參數

大致如下圖所示:

zone初始化過程


free_area_init_node函數

free_area_init_node實現1

第78~79行:初始化pg_data_t中的node_id內存節點ID和node_start_pfn內存節點起始頁框號第80~84行:如果定義了CONFIG_HAVE_MEMBLOCK_NODE_MAP計算得到本內存節點內的物理頁框起始結束編號,get_pfn_range_for_nid函數和實現細節如下↓第85行:計算內存節點內總的頁框數(包含空洞),實現細節如下↓

free_area_init_node實現2

第88行:初始化pgdat.node_mem_map,實現細節見alloc_node_mem_map函數↓第95行:初始化內存節點內各個zone的實際處理函數,實現細節見free_area_init_core函數↓get_pfn_range_for_nid函數

get_pfn_range_for_nid實現

在get_pfn_range_for_nid函數主要是看for_each_mem_pfn_range宏的實現,而for_each_mem_pfn_range的實現主要看__next_mem_pfn_range函數的實現,以下就是該函數的實現細節↓__next_mem_pfn_range函數

__next_mem_pfn_range實現

遍歷當前memory_type下的所有regions,每遍歷一個region獲取該region的起始頁框號返回。另外需要指出的是如果當前nid等於MAX_NUMNODES說明所有內存節點已經處理完畢。返回到get_pfn_range_for_nid函數中與已有起始結束頁框號進行比較,起始頁框號取最小,結束頁框號取最大。當本內存節點內的region都遍歷完畢,最終在start_pfn和end_pfn中就會保存內存節點的起始結束物理頁框編號calculate_node_totalpages函數

calculate_node_totalpages實現

第41~46行:計算內存節點(包含空洞在內的)總頁框數,並初始化pgdat中的node_spanned_pages第48~54行:計算內存節點內(不包含空洞區域)總頁框總數,並初始化pgdat中的node_present_pageszone_spanned_pages_in_node和zone_absent_pages_in_node這兩個函數的實現細節如下↓

zone_spanned_pages_in_node和zone_absent_pages_in_node實現

在內存管理(13)zone初始化1中有分析過zones_size和zholes_size所表示的含義

平坦內存模型則處理alloc_node_mem_map函數

alloc_node_mem_map函數

alloc_node_mem_map 實現1

alloc_node_mem_map 實現2

第66行:如果定義了CONFIG_FLAT_NODE_MEM_MAP(平坦內存模型),平坦內存模型意味著沒有空洞,在此前提之下。如果沒有初始化pgdat->node_mem_map則對其執行初始化處理。主要以1K頁為對齊計算起始終止頁框號。ZONE起始頁框位置忽略小於1K頁框數的部分,ZONE結束頁框的位置低於1K頁的向上取整K頁框數記做end,這麼做是為了方便夥伴系統按2^ORDER的順序進行頁框分配。計算總的(end-start)頁的struct page數據結構所佔用空間,然後向memblock申請這段空間並用map指向它。第85行:假設內存節點的物理起始頁框編號本來是1025,前面為了方便夥伴系統按MAX_ORDER序列分配頁框,使其與1024對齊所以start被記做1024,這時候計算的struct page所佔用內存為end-1024 而實際有效的物理頁框是從1025開始的所以才有了第85行這一步,node_mem_map偏移(node_start_pfn - start)個頁框,使其指到有效位置。最後87~97行主要就做一件事,系統內存節點是否為單節點,是的話就用mem_map全局變量來記錄pgdat->node_mem_mapfree_area_init_core函數

free_area_init_core 實現1

第111行:如果定義了CONFIG_MEMORY_HOTPLUG初始化pgdat->node_size_lock第112~115行:如果定義了CONFIG_NUMA_BALANCING初始化BALANCING相關成員第117~119行:初始化其他一些pgdat相關成員第121行:開始遍歷ZONE第125行:計算當前zone下包含空洞在內所佔的總頁框數第127行:計算當前zone除空洞外所佔頁框數第137行:以頁為單位計算當前zone裡頁框的struct page數據結構所佔物理頁框數,calc_memap_size實現如下↓第138~145行:減去struct page所佔物理頁框數,重新計算非高端內存的空閒空間物理頁框數

free_area_init_core 實現3

第152~156行:如果有DMA,則減去DMA保留空間所佔的物理頁框數計算剩餘空閒空間物理頁框數第157~161行:統計直接映射的物理頁框數,用nr_kernel_pages全局變量保存第162行:統計剩餘可用的空閒空間頁框數,用nr_all_pages全局變量保存第164~165行:初始化zone的spanned_pages和present_pages第171行:初始化zone的managed_pages,如果是高端內存則managed_pages就是實際的物理頁框數,如果是低端內存那麼managed_pages是系統ZONE中剩餘的空閒頁框數第172~177行:初始化針對NUMA系統的其他參數

free_area_init_core 實現4

第178~182行:初始化zone的相關成員第183行:初始化per_cpu的pageset管理單個CPU頁框數據結構,緩解鎖的競爭第186行:看了半天沒看懂什麼意思(先留個疑問吧)第192行:檢查pageblock是否設定第193行:未定義CONFIG_SPARSEMEM時計算zone裡面page_flags所佔內存空間大小,setup_usemap函數實現細節↓第194行:初始化等待隊列散列表,init_currently_empty_zone實現如下↓第197行:初始化zone下所有page數據結構的相關參數,memmap_init_zone函數實現如下↓calc_memmap_size函數

calc_memmap_size實現

這個函數的關鍵就是第335行,為什麼要做這麼一個判斷呢,它要表達的意思很簡單如果spanned_page比present_page多超過present_page的1/16,並且內存模型是稀疏內存模型,那麼就使用present_page來計算struct page所佔用的空間。因為在稀疏內存模型下,zone內部可能有空洞,系統為了儘可能的權衡,所以使用present來計算memmap映射的page數據結構所佔空間。而當其小於present_page的1/16,則仍舊使用spanned_pages來計算。setup_usemap函數

setup_usemap實現

在setup_usemap函數中第348行看usemap_size函數的實現細節可知,每個pageblock用4個bits來表示pageblock_flags,所以usemap_size其實就是計算所有的pageblock_flags所佔用的字節空間而352行就是在計算到這段空間大小後申請它,並用pageblock_flags指向它init_currently_empty_zone函數

init_currently_empty_zone實現

第429行:初始化進程等待隊列散列表數組,zone_wait_table_init實現如下↓第442行:初始化ZONE空閒鍊表,zone_init_free_lists函數實現如下↓zone_wait_table_init函數

zone_wait_table_init實現

這個函數中主要初始化了進程等待隊列散列表相關的參數信息,其中wait_table表示進程等待一個page釋放的等待隊列哈希表。它會被wait_on_page,unlock_page函數使用. 用哈希表,而不用一個等待隊列的原因,防止進程長期等待資源。wait_table_hash_nr_entries表示哈希表中的等待隊列的數量。wait_table_bits表示等待隊列散列表數組的大小。他們相當於如下一個模型,等待隊列模型如下圖所示:

等待隊列模型

zone_init_free_lists函數

zone_init_free_lists實現

如文章開頭所提示意圖,每個ZONE下對應一個free_area數組,數組大小為MAX_ORDER,在系統中MAX_ORDER大小設為11,在每一個free_area中都包含MIGRATE_TYPES個鍊表,如上圖所示MIGRATE_UNMOVABLE、MIGRATE_RECLAIMABLE、MIGRATE_MOVABLE各對應一條空閒頁框鍊表下頁框屬性,鍊表中節點所佔頁框數就是2^index個頁框。

memmap_init_zone函數主要就是初始化page數據結構相關的一些參數。所以在描述這個函數之前有必要先就struct page 數據結構的某些關鍵成員做一個簡單介紹

struct page數據結構(部分)

struct page結構體

flags:描述page的狀態和其他信息。由section node zone flags組成,其中section用於稀疏內存模型,node表示當前頁所佔的內存節點,zone表示當前頁所在的內存域flags代表頁狀態。

比較常用的幾種flags如下:

page.flags標誌定義

_count:引用計數,表示內核中引用該page的次數,如果要操作該page引用計數會 1,操作完成-1。當該值為0時,表示沒有引用該page的位置,所以該page可以被解除映射,這往往在內存回收時是有用的。_mapcount:被頁表映射的次數,也就是說該page同時被多少個進程共享。初始值為-1,如果只被一個進程的頁表映射了,該值為0 。如果該page處於夥伴系統中,該值為PAGE_BUDDY_MAPCOUNT_VALUE(-128),內核通過判斷該值是否為PAGE_BUDDY_MAPCOUNT_VALUE來確定該page是否屬於夥伴系統。


注意區__count和_mapcount,_mapcount表示的是映射次數,而_count表示的是使用次數;被映射了不一定在使用,但要使用必須先映射。

mapping:有三種含義:如果mapping = 0,說明該page屬於交換緩存(swap cache),當需要使用地址空間時會指定交換分區的地址空間swapper_space;如果mapping != 0,bit[0] = 0,說明該page屬於頁緩存或文件映射,mapping指向文件的地址空間address_space; 如果mapping != 0,bit[0] != 0,說明該page為匿名映射,mapping指向struct anon_vma對象。index:在映射的虛擬空間(vma_area)內的偏移;一個文件可能只映射一部分,假設映射了1M的空間,index指的是在1M空間內的偏移,而不是在整個文件內的偏移。private:私有數據指針,由應用場景確定其具體的含義:如果設置了PG_private標誌,表示buffer_heads; 如果設置了PG_swapcache標誌,private存儲了該page在交換分區中對應的位置信息swp_entry_t。 如果_mapcount = PAGE_BUDDY_MAPCOUNT_VALUE,說明該page位於夥伴系統,private存儲該夥伴的階。lru:鍊表頭,主要有3個用途:a:page處於夥伴系統中時,用於連結相同階的夥伴(只使用夥伴中的第一個page的lru即可達到目的)。 b:page屬於slab時,page->lru.next指向page駐留的緩存的管理結構,page->lru.prec指向保存該page的slab的管理結構。 c:page被用戶態使用或被當做頁緩存使用時,用於將該page連入zone中相應的lru鍊表,供內存回收時使用。memmap_init_zone函數

memmap_init_zone 實現1

第213行確定zone地址;第214行遍歷zone下的頁框;第226行確定頁框地址


memmap_init_zone 實現2

第227行:set_page_links函數確定page所在的section、node、zone,設定到page->flags中,set_page_links的實現如下↓第228行:檢測section等的合法性第229~230行:初始化page->_count,頁框引用次數;page->_mapcount映射次數第231~232行:初始化page相關參數第234~237行:表示把每個pageblock的第一個page屬性設置為MIGRATE_MOVEABLE初始化page相關其他參數set_page_links函數

set_page_links實現

從set_page_links函數的實現可以看出section、node、zone處在flags中的位置大致如下:

flags結構

左邊代表高位,右邊為低位


zone的初始化基本介紹完畢。其初始化過程基本如開篇所給出的圖那樣。當然這只是初始化的介紹,後面介紹諸如頁的交換、回收、映射、分配等很多場景中會再次介紹其中很多參數所起的實際作用,這裡沒有說只是覺得說了也沒什麼意義,只有真正用到的時候我們才會明白其真正的含義。

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了