iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Software Development

閱讀 Linux Kernel 文件系列 第 17

# Day 17 Physical Memory Model (二)

文件

SPARSEMEM
=========

SPARSEMEM 是 Linux 中最萬用的記憶體模型,它也是唯一支援多種進階功能的記憶體模型,
例如:實體記憶體的熱插拔、非揮發性儲存裝置的替代記憶體映射、和大型系統的延遲初始化記憶體映射。

SPARSEMEM 模型用區段(section)的集合來表示實體記憶體。
一個區段用 struct mem_section 來表示,
而 struct mem_section 中包含 `section_mem_map`,
`section_mem_map` 邏輯上是一個指向 struct page 陣列的指標。
而它還含有一些其他的"魔術"來協助區段管理。
區段的大小和區段的最大數量是由 `SECTION_SIZE_BITS` 和 `MAX_PHYSMEM_BITS` 常數所標示,
這兩個常數則是由有支援 SPARSEMEM 模型的架構來各自定義。
`MAX_PHYSMEM_BITS` 是架構所支援的實際實體記憶體寬度,而 `SECTION_SIZE_BITS` 是一個任意值。

區段的最大數量表示為 “NR_MEM_SECTIONS” 和被定義為
.. math::

   NR\_MEM\_SECTIONS = 2 ^ {(MAX\_PHYSMEM\_BITS - SECTION\_SIZE\_BITS)}

`mem_section` 物件是由一個二維陣列稱為 `mem_sections` 來管理。
這個陣列的大小和位置取決於在 `CONFIG_SPARSEMEM_EXTREME` 和區段的最大可能數量:

* 當 `CONFIG_SPARSEMEM_EXTREME` 被禁用(disabled)時,
  `mem_sections` 陣列是靜態的(static),有 “NR_MEM_SECTIONS” 列(row)。
  每一列存有一個 `mem_section` 物件。

* 當啟用 `CONFIG_SPARSEMEM_EXTREME` 時,
  `mem_sections` 陣列是動態分配的。
  每列一包含 PAGE_SIZE 這麼多的 `mem_section` 物件,
  而列的數量則是剛好對應所有的記憶體區段。

架構設置程式碼需要呼叫 sparse_init() 來初始化記憶體區段部分和記憶體映射。

SPARSEMEM 中,有兩種方法可以將 PFN 轉換為相應的`struct page` 
- “classic sparse” 和 “sparse vmemmap”。
使用哪種方法是在編譯時進行的,它由 `CONFIG_SPARSEMEM_VMEMMAP` 的值來決定。

classic sparse 將分頁的區段號碼編碼在 page->flags 中,
並使用 PFN 的高位元來存取映射該分頁框的區段。
在區段內,PFN 是分頁陣列的索引。

sparse vmemmap 使用虛擬的記憶體映射來優化 pfn_to_page 和 page_to_pfn。
有一個全域的 `struct page *vmemmap` 指標指向一個連續的 `struct page` 物件陣列,
PFN 是該陣列的索引,而 `vmemmap` 到 `struct page` 的偏移量是該分頁的 PFN。

要使用 vmemmap,支援的架構必須保留一個範圍的虛擬位址,
這段虛擬位址會映射含有記憶體映射的實體分頁,並且確保 `vmemmap` 指向該範圍。
此外,該架構需要實做 :c:func:`vmemmap_populate`,
它將分配實體記憶體並為虛擬記憶體映射創造分頁表。
如果架構沒有任何特殊的 vmemmap 映射需求,
可以使用通用記憶體管理提供的 :c:func:`vmemmap_populate_basepages`。

虛擬映射的記憶體映射允許在非揮發性儲存裝置上的域先分配記憶體中儲存 `struct page` 物件。
該儲存用 struct vmem_altmap 表示且最終通過一長串的函數呼叫傳遞給 vmemmap_populate()。 vmemmap_populate() 的實作可以使用 `vmem_altmap` 以及 :c:func:`vmemmap_alloc_block_buf`
來幫助程序在非揮發性儲存裝置上分配記憶體映射。

我的理解

  • Each row contains PAGE_SIZE worth of "mem_section" objects 指的是,mem_section 物件數量有 PAGE_SIZE/sizeof(mem_section) 這麼多個。
  • 內文中有提到很多次 virtually mapped memory mapmemory mapphysical pages containing the memory map,還不是太清楚這裡的 memory map 指的是什麼~

後記

今天是文件第二部分的翻譯,提到 SPARSEMEM、SPARSEMEM 的部分實作要求,以及實作的撇步。
第三部分以及內容整理,我們就留待明日了!感謝各位!


上一篇
# Day 16 Physical Memory Model(一)
下一篇
# Day 18 Physical Memory Model (三)
系列文
閱讀 Linux Kernel 文件30

尚未有邦友留言

立即登入留言