Linux內存管理專題

Linux的內存管理涉及到的內容很是龐雜,並且與內核的方方面面耦合在一塊兒,想要理解透徹很是困難。html

在開始學習以前進行了一些準備工做《如何展開Linux Memory Management學習?》,linux

1. 參考資料

遂決定以以下資料做爲參考,進行Linux內存管理的研究:git

奔跑吧 Linux內核》:以第2章爲藍本展開,這是目前能獲取的緊跟當前內核發展(Linux 4.0),而且講的比較全面的一本資料。github

Understanding the Linux Virtual Memory Manager》:簡單說就是雖老但經典,基於(Linux 2.4/2.6)。做者是目前仍然活躍在Linux社區MM專家。算法

wowotech Memory Management》:沒有其餘系列經典,也沒有條理系列的介紹MM,可是仍然值得按考。shell

tolimit Linux內存源碼分析》:相對零散的介紹了內存相關分析文檔express

Linux Kernel v4.0》:固然必不可少的,是源碼了。ubuntu

當逐漸深刻看到MMU相關代碼時,讀一下ARM架構關於MMU的規格書有助於理解。小程序

否則對於虛擬地址到物理地址的映射就會很虛無,這些資料包括《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》的《Virtual Memory System Architecture》,以及相關MMU TRM。數據結構

2. Linux Memory Management框架圖

 整個內存管理從宏觀上能夠分爲三大部分:用戶空間、內核空間和相關硬件

用戶空間主要是libc對相關係統調用進行封裝,對用戶程序提供API,經常使用的有malloc、mmap、munmap、remap、madvise、mempolicy等等。

相關硬件包括MMU/TLB、L1/L2 Cache以及DDR RAM,具體到ARM架構須要對照MMU/L2 Cache以及RAM規格書。

內核空間就複雜多了,首先介紹初始化及初始化後的佈局。

2.1 物理內存初始化從獲取內存大小、初始化頁表,再進行zone初始化,而後在zone中使用夥伴系統進行物理內存初始化;

2.2 頁表的映射過程講述了ARM32和ARM64兩種架構下的頁表映射,如何從虛擬地址由MMU轉化成物理頁面地址的;

2.3 內核內存的佈局圖在內存被初始化以後,內核的內存佈局基本上就肯定了,ARM32和ARM64下佈局有很大區別。在malloc一節brk中介紹了用戶空間的佈局。

 

2.1~2.3是內存的一個靜態狀態,在有了這些基礎以後,2.4~2.9按照從低層到上層的逐個介紹了。

2.4 分配物理頁面介紹了基於夥伴系統的頁分配和釋放;

2.5 slab分配器基於夥伴系統,slab分配更小內存塊;以及基於slab的kmalloc;

2.6 vmalloc和kmalloc區別在於v,即在VMALLOC區域分配;

2.7 VMA即Virtual Memory Area,是進程內存管理的核心;

2.8 malloc2.9 mmap都基於VMA,malloc/free用於分配/釋放一塊內存;mmap/munmap用於匿名/文件映射到用戶空間。以及mmap(補充)

因爲malloc/mmap分配內存並非當即分配,只是在用到的時候纔會觸發2.10 缺頁中斷處理

 

在缺頁但頁不足的狀況下,就須要進行一些操做調整內存,這些操做的基礎是2.11 page引用計數,還有頁面的2.12 反向映射RMAP技術。

在內存不足狀況下觸發kswapd2.13 回收頁面,其中匿名頁面有着特殊的2.14 匿名頁面生命週期

在kswapd回收依然沒法知足內存分配,就須要對內存進行2.16 內存規整,它依賴的技術是2.15 頁面遷移

因爲內存中存在一些內容徹底同樣的頁面,使用2.17 KSM技術進行合併,同時利用COW技術,在須要時從新分配。

還介紹了2.18 Dirty COW內存漏洞,而後對內存管理數據結構和API進行了總結2.19 總結內存管理數據結構和API

最後2.20 最新更新和展望對新技術進行了介紹。

除了以上技術,還有以下內存技術:

  • swap計數把匿名頁面寫入SWAP分區從而釋放出空閒頁面
  • 內存壓縮技術zram(a compressed RAM based swap device)
  • zswap技術是zram和swap的一個綜合,首先將待換出頁面進行壓縮,存儲到系統RAM動態分配的內存池中;達到必定閾值後再寫入實際交換設備。
  • 在內存極端不足狀況下使用21 OOM(Out-Of-Memory)來殺死不重要進程獲取更多內存的技術
  • 基於cgroup的Memory資源控制
  • 解決多媒體對大量連續內存需求的CMA(Contiguous Memory Allocator)技術
  • slub分配器
  • memory hotplug內存熱插拔支持動態更換內存物理設備

==============================================================================================================================

在對內存相關技術瞭解事後,就是如何運用的問題了?

一方面是對內存問題進行定位;另外一方面是對內存行爲施加影響,進行優化。

22 內存檢測技術對Linux內存常見問題及其定位方法和工具(slub_debug/kmemleak/kasan)進行了講解。

23 一個內存Oops解析以一個內存Oops爲例,介紹了內存相關異常分析。

內存sysfs節點和工具介紹了linux內存管理相關sysfs節點,以及工具;藉助這些能夠對內存進行優化。

擴展閱讀:

Linux內存管理框架圖

3. 代碼和測試環境搭建

3.1 QEMU

安裝QEMU以及相關編譯工具

sudo apt-get install qemu libncurses5-dev gcc-arm-linux-gnueabi build-essential

3.2 Busybox 1.24

下載Busybox 1.24代碼:

git clone https://github.com/arnoldlu/busybox.git -b 1_24_stable

編譯Busybox:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi- #make menuconfig #P684,進行配置 make -j4 install

 

配置initramfs:

sudo cp -r running_kernel_initramfs/* _install/
sudo chmod +x _install/etc/init.d/rcS
cd _install
mkdir mnt
mkdir dev
cd dev
sudo mknod console c 5 1
sudo mknod null c 1 3

  

3.3 Kernel 4.0

下載Linux Kernel 4.0代碼:

git clone https://github.com/arnoldlu/linux.git -b running_kernel_4.0

 編譯Linux Kernel:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make vexpress_defconfig #P685進行配置 make bzImage -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make dtbs

  

3.4 運行內核

#Run Kernel+Busybox in QEMU
qemu-system-arm -M vexpress-a9 -smp 4 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic

 至此,已經有一個完整的環境,提供shell命令。

 

4. 思考問答

  1. 在系統啓動時,ARM Linux內核如何知道系統中有多大的內存空間?
  2. 在32bit Linux內核中,用戶空間和內核空間的比例一般是3:1,能夠修改爲2:2嗎?
  3. 物理內存頁面如何添加到夥伴系統中,是一頁一頁添加,仍是以2的幾回冪來加入呢?
  4. 內核的一級頁表存放在什麼地方?二級頁表又存放在什麼地方?
  5. 用戶進程的一級頁表存放在什麼地方?二級頁表呢?
  6. 在ARM32系統中,頁表是如何映射的?在ARM64系統中,頁表又是如何映射的?
  7. 請簡述Linux內核在理想狀況下頁面分配器(page allocator)是如何分配出連續物理頁面的。
  8. 在頁面分配器中,如何從分配掩碼(gfp_mask)中肯定能夠從哪些zone中分配內存?
  9. 頁面分配器是按照什麼方向來掃描zone的?
  10. 爲用戶進程分配物理內存,分配掩碼應該選用GFP_KERNEL,仍是GFP_HIGHUSER_MOVABLE呢?
  11. slab分配器是如何分配和釋放小塊內存的?
  12. slab分配器中有一個着色的概念(cache color),着色有什麼做用?
  13. slab分配其中的slab對象有沒有根據Per-CPU作一些優化?
  14. slab增加並致使大量不用的空閒對象,該如何解決?
  15. 請問kmalloc、vmalloc和malloc之間有什麼區別以及實現上的差別?
  16. 使用用戶態的API函數malloc()分配內存時,會立刻爲其分配物理內存嗎?
  17. 假設不考慮libc的因素,malloc分配100Byte,那麼實際上內核是爲其分配100Byte嗎?
  18. 假設兩個用戶進程打印的malloc()分配的虛擬地址是同樣的,那麼在內核中這兩塊虛擬內存是否打架了呢?
  19. vm_normal_page()函數返回的是什麼樣頁面的struct page數據結構?爲何內存管理代碼中須要這個函數?
  20. 請簡述get_user_page()函數的做用和實現流程?
  21. 請簡述follow_page()函數的做用和實現流程?
  22. 請簡述私有映射和共享映射的區別。
  23. 爲何第二次調用mmap時,Linux內核沒有捕捉到地址重疊並返回失敗呢?
  24. struct page數據結構中的_count和_mapcount有什麼區別?
  25. 匿名頁面和page cache頁面有什麼區別?
  26. struct page數據結構中有一個鎖,請問trylock_page()和lock_page()有什麼區別?
  27. 在Linux 2.4.x內核中,如何從一個page找到全部映射該頁面的VMA?反響映射能夠帶來哪些便利?
  28. 閱讀Linux 4.0內核RMAP機制的代碼,畫出父子進程之間VMA、AVC、anon_vma和page等數據結構之間的關係圖。
  29. 在Linux 2.6.34中,RMAP機制採用了新的實現,在Linux 2.6.33和以前的版本中稱爲舊版本RMAP機制。那麼在舊版本RMAP機制中,若是父進程有1000個子進程,每一個子進程都有一個VMA,這個VMA裏面有1000個匿名頁面,當全部的子進程的VMA同時發生寫複製時會是什麼狀況呢?
  30. 當page加入lru鏈表中,被其餘線程釋放了這個page,那麼lru鏈表如何知道這個page已經被釋放了。
  31. kswapd內核線程什麼時候會被喚醒?
  32. LRU鏈表如何知道page的活動頻繁程度?
  33. kswapd按照什麼原則來換出頁面?
  34. kswapd按照什麼方向來掃描zone?
  35. kswapd以什麼標準來退出掃描LRU?
  36. 手持設備例如Android系統,沒有swap分區或者swap文件,kswapd會掃描匿名頁面LRU嗎?
  37. swappiness的含義是什麼?kswapd如何計算匿名頁面和page cache之間的掃描比重?
  38. 當系統充斥着大量只訪問一次的文件訪問(use-one streaming IO)時,kswapd如何來規避這種風暴?
  39. 在回收page cache時,對於dirty的page cache,kswapd會立刻回寫嗎?
  40. 內核有哪些頁面會被kswapd寫回交換分區?
  41. ARM32 Linux如何模擬這個Linux版本的L_PTE_YOUNG比特位呢?
  42. 如何理解Refault Distance算法?
  43. 請簡述匿名頁面的生命週期。在什麼狀況下會產生匿名頁面?在什麼條件下會釋放匿名頁面?
  44. KSM是基於什麼原理來合併頁面的?
  45. 在KSM機制裏,合併過程當中把page設置成寫保護的函數write_protect_page()有這樣一個判斷:。這個判斷的依據是什麼?
  46. 若是多個VMA的虛擬頁面同時映射了同一個匿名頁面,那麼此時page->index應該等於多少?
  47. 爲何Dirty COW小程序能夠修改一個只讀文件的內容?
  48. 在Dirty COW內存漏洞中,若是Diryt COW程序沒有madviseThread線程,即只有procselfmemThread線程,可否修改foo文件的內容呢?
  49. 假設在內核空間獲取了某個文件對應的page cache頁面的struct page數據結構,而對應的VMA屬性是隻讀,那麼內核空間是否能夠成功修改該文件呢?
  50. 若是用戶進程使用只讀屬性(PROT_READ)來mmap映射一個文件到用戶空間,而後使用memcpy來寫這段內存空間,會是什麼樣的狀況?
  51. 請畫出內存管理中經常使用的數據結構的關係圖,如mm_struct、vma、vaddr、page、pfn、pte、zone、paddr和pg_data等,並思考以下轉換關係。
  52. 請畫出在最糟糕的狀況下分配若干個連續物理頁面的流程圖。
  53. 在Android中新添加了LMK(Low Memory Killer),請描述LMK和OOM Killer之間的關係。
  54. 請描述一致性DMA映射dma_alloc_coherent()函數在AEM中是如何管理cache一致性的?
  55. 請描述流式DMA映射dma_map_single()函數在ARM中是如何管理cache一致性的?
  56. 爲何在Linux 4.8內核中要把基於zone的LRU鏈表機制遷移到基於Node呢?
相關文章
相關標籤/搜索