tft每日頭條

 > 生活

 > 内存基址和内存地址

内存基址和内存地址

生活 更新时间:2024-10-14 11:35:27

内存管理(11)物理地址空間的有效性檢測主要講述了Linux内核是如何從memblock.memory

->regions->page->section->mem_section建立物理地址之間關系的。但是我們并沒有對mem_section所管理的有效頁框創建相應的映射關系以及初始化每個section下的頁框屬性。所以linux 内核是如何完成這件事的呢?

1.遍曆系統中所有可能存在的section,過濾無效的,計算每一個node中有多少個有效的section

2.為每個node申請一個元素數量為有效section個數數量相等的unsigned long*指針數組

3.把每個有效section的unsigned long*指針數組中的指針指向一個數組,這個數組存放了當前section裡面所有頁的pageblock_flags

4.mem_section.section_mem_map使用了同樣的套路

内存基址和内存地址(内存管理12物理地址空間的有效性檢測)1

系統中稀疏内存模型分布圖

sparse_init函數

内存基址和内存地址(内存管理12物理地址空間的有效性檢測)2

  • 第17行:設置pageblock_order大小,相關函數實現細節如下↓

  • 内存基址和内存地址(内存管理12物理地址空間的有效性檢測)3

    sparse_init實現(2)

    • 第30~31行:Linux内核向memblock申請了NR_MEM_SECTIONS * sizeof(unsigned long *)字節的空間,用usemap_map指向其首地址。其中NR_MEM_SECTIONS的含義請參閱内存管理(11)物理地址空間的有效性檢測,那這個空間用來做什麼,繼續往下看。

    • 第34行:alloc_usemap_and_memmap中遍曆系統中所有的section,計算出系統中每個node下的有效section數,函數實現如下↓。每遍曆完一個node後,就在sparse_early_usemaps_alloc_node中為該node下所有有效的section裡面所有的pageblock_flags申請空間,然後遍曆每一個section将其對應usemap_map指向對應的pageblock_flags數組首地址,因此上面申請的usemap_map集合中的每一個unsigned long *都會指向對應section下的pageflags數組,相關函數實現如下

    • 第38~40行:如果定義了CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER,申請NR_MEM_SECTIONS * sizeof(struct page *)大小的空間,用map_map指向它。那這個map_map又是用來做什麼的,繼續往下看

    • 第42~43行:在上文已解釋alloc_usemap_and_memma函數。在sparse_early_mem_maps_alloc_node ->sparse_mem_maps_populate_node中如果定義了CONFIG_SPARSEMEM_VMEMMAP那麼sparse_mem_maps_populate_node中遍曆了每一個有效的section,用前面申請的map_map中的每一個struct page *都建立了對應于section的一系列頁框數組的虛拟映射表,比如section[pnum]其對應的map_map[pnum]就會被用來建立一個虛拟映射表,它指向對應section下所有頁框的虛拟映射表空間,map_map[pnum]最終會被用去初始化mem_section[pnum].section_mem_map.

    • 第46~48行:遍曆所有的section,過濾無效的section

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)4

    sparse_init實現(3)

    • 第54~58行:如果定義了CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER就取對應section的map_map,否則對對應section下的map在函數sparse_early_mem_map_alloc->sparse_mem_map_populate中真正的建立映射關系,其實現細節如下↓

    • 第62行:将前面得到的pageblock_flags和map填充到對應section的mem_section中

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)5

    sparse_init實現(4)

    set_pageblock_order函數

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)6

    set_pageblock_order實現

    • 第107行:定義了超巨頁的話pageblock_order = HPAGE_SHIFT - PAGE_SHIFT = 21 - 12 = 9

    • 第109行:沒有定義超巨頁pageblock_order = MAX_ORDER - 1 = 11 - 1 = 10

    alloc_usemap_and_memmap函數:

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)7

    alloc_usemap_and_memmap實現(1)

    • 第128~132行:遍曆系統中所有的section,過濾掉無效section

    • 第138行:同一個node,一個有效section記做一次map

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)8

    alloc_usemap_and_memmap實現(2)

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)9

    alloc_usemap_and_memmap實現(3)

    • 第139~162行:計算一個node裡面有多少個有效的section需要進行多少次map,并在每遍曆完一個node後或對其pageblock_flags進行初始化或對其section_mem_map建立虛拟映射表

    sparse_early_usemaps_alloc_node函數

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)10

    sparse_early_usemaps_alloc_node實現

    • 第259行:計算一個node裡面每個有效section的pageblock_flags所占用的空間大小,每個pageblock_flags使用4bit進行存放

    • 為當前node下所有有效section的pageblock_flags申請空間并且用usemap指向它

    • 為每一個section index為下标的usemap_map以此初始化use_map,為最終mem_section中的pageblock_flags初始化做準備

    sparse_early_mem_map_alloc->sparse_mem_map_populate函數

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)11

    sparse_mem_map_populate實現

    • 第302行:通過頁框号找到對應物理地址

    • 第304行:根據頁框數量偏移得到結尾頁框地址

    • 第306行:建立映射關系的實際函數,實現↓

    vmemmap_populate函數

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)12

    vmemmap_populate實現(1)

    内存基址和内存地址(内存管理12物理地址空間的有效性檢測)13

    vmemmap_populate實現(2)

    • 本文的重點在于Linux内核是怎麼對mem_section中的section_mem_map和pageblock_flags初始化的。所以這個函數暫不分析,因為實在太晚了,該睡覺了~ 其實有一部分在前面分析過。

    ,

    更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

    查看全部

    相关生活资讯推荐

    热门生活资讯推荐

    网友关注

    Copyright 2023-2024 - www.tftnews.com All Rights Reserved