1.前言
本文所述關於內存管理的系列文章主要是對陳莉君老師所講述的內存管理知識講座的整理。
本講座主要分三個主題展開對內存管理進行講解:內存管理的硬件基礎、虛擬地址空間的管理、物理地址空間的管理.
本文將主要以X86架構為例來介紹虛擬地址空間的管理。
2.虛擬地址空間展示
圖 進程地址空間
- 程序一旦被執行就成為一個進程,內核就會為每個運行的進程提供了大小相同的虛擬地址空間,這使得多個進程可以同時運行而又不會互相干擾
- 具體來說一個進程對某個地址的訪問,絕不會干擾其他進程對同一地址的訪問。
- 每個進程都擁有4GB(32位)大小的虛擬地址空間,每個進程都擁有私有的前3G空間,即“用戶空間”;而后1G空間被每個進程所共享,即“內核空間”。
- 進程訪問內核空間的唯一途徑為系統調用。
- 在每個進程眼中,它們各自擁有4GB大小的地址空間;而在CPU眼中,任意時刻,一個CPU上只存在一個虛擬地址空間。虛擬地址空間隨着進程間的切換而變化。
3.虛擬內存實現機制
圖 虛擬內存實現機制
- 地址映射
可執行文件從磁盤映射到虛擬地址空間
虛擬地址空間映射到物理地址空間
- 請頁
將可執行文件從磁盤調入物理內存
- 內存的分配與回收
- 緩存和刷新
- 交換機制
把內存的內容換到磁盤,把磁盤內容換到內存,需要用到文件系統
4. 進程地址空間布局圖
圖 進程地址空間布局圖
- Linux把進程的地址空間划分為多個區間,這些區間稱為虛擬內存區域(VMA)
- 可以通過cat /proc/進程號/maps來查看進程的地址空間布局
圖 mymmap可執行文件的內存布局
5. 進程用戶空間的描述
- 一個進程的用戶地址空間主要由mm_struct結構和vm_area_structs結構來描述
- mm_struct結構對進程整個用戶空間進行描述
- mm_area_structs結構對用戶空間中各個內存區進行描述
- mm_struct內存描述符基本字段
圖 內存描述符基本字段
- vm_area_structs主要字段
圖 vm_area_structs主要字段
6. 相關數據結構之間的關系
圖 相關數據結構之間的關系
- 進程在內核中通過task_struct結構體進行描述
- task_struct->mm指向與該進程用戶空間對應的mm_struct結構體
- mm_struct->mmap指向VMA雙鏈表
- 使用current->mm->mmap可獲得VMA鏈表的頭指針
- current->mm->mmap->vm_next獲得指向該VMA雙鏈表的下一個結點的指針
7. 新建虛擬內存區域
圖 mmap()和do_mmap()
- 在內核空間通過do_mmap()創建一個新的虛擬內存區域
- 在用戶空間通過mmap()系統調用獲取do_mmap()的功能
8.內存映射
- 內存映射
把文件從磁盤映射到進程用戶空間的一個虛擬內存區域中,對文件的訪問轉化為對虛存區的訪問。
當從這段虛擬內存中讀數據時,就相當於讀磁盤文件中的數據,將數據寫入這段虛擬內存時,則相當於將數據直接寫入磁盤文件。
這樣就可以在不使用基本I/O操作函數read和write的情況下執行I/O操作。
有共享的、私有的虛存映射和匿名映射
- mmap()函數
圖 mmap函數說明
- mmap的演示
如下實現了將磁盤文件mapping_file.txt映射到進程的虛擬用戶空間,通過修改首字符,實現對文件的讀寫
圖 mmap的演示
9.虛擬內存與物理內存
(1)用戶態的程序經過編譯執行形成進程,進程雖然可以任意訪問整個用戶空間的內存,但這畢竟屬於虛擬地址空間,因此進程最終必須訪問到物理內存。
(2)將虛擬內存和物理內存連接起來的就是分頁機制,它在虛擬地址和物理地址之間建立了一種映射關系。
(3)進程訪問的是虛擬地址,虛擬地址通過頁表的轉換最終形成物理地址。如果某個虛擬地址在頁表中並不存在和某個物理地址之間的映射,那么系統將發生一次缺頁異常。
(4)當一個進程運行時,CPU訪問的地址是用戶空間的虛擬地址。Linux采用請頁機制來節約物理內存,也就是說它僅僅將當前要使用的用戶空間中少量頁裝入物理內存。
(5)當訪問的虛擬內存頁面尚未裝入物理內存時,處理器將產生一個缺頁異常。當發生缺頁異常時,操作系統必須從磁盤或交換文件中將要訪問的頁裝入物理內存。
10. 參考文獻
[7].GNU的C語言,http://www.faqs.org/docs/learnc/
[8].GCC參考手冊