直觀對比
- 物理內存:也就是安裝在計算機中的內存條,比如安裝了 2GB 大小的內存條,那么物理內存地址的范圍就是 0 ~ 2GB。這也是CPU可以直接進行尋址的內存空間大小
- 虛擬內存:虛擬的內存地址。由於 CPU 只能使用物理內存地址,所以需要將虛擬內存地址轉換為物理內存地址才能被 CPU 使用,這個轉換過程由 MMU(Memory Management Unit,內存管理單元) 來完成。虛擬內存大小不受物理內存 大小的限制,在 32 位的操作系統中,每個進程的虛擬內存空間大小為 0 ~ 4GB。
內存分布
程序中使用的內存地址都是虛擬內存地址,也就是說,我們通過 malloc 函數申請的內存都是虛擬內存。實際上,內核會為每個進程管理其虛擬內存空間,並且會把虛擬內存空間划分為多個區域,如下圖:
- 代碼段:用於存放程序的可執行代碼。
- 數據段:用於存放程序的全局變量和靜態變量。
- 堆空間:用於存放由 malloc 申請的內存。
- 棧空間:用於存放函數的參數和局部變量。
- 內核空間:存放 Linux 內核代碼和數據。
虛擬空間都被映射到了磁盤空間中,(事實上也是按需要映射到磁盤空間上,通過mmap),並且由頁表記錄映射位置,當訪問到某個地址的時候,通過頁表中的有效位,可以得知此數據是否在內存中,如果不是,則通過缺頁異常,將磁盤對應的數據拷貝到內存中,如果沒有空閑內存,則選擇犧牲頁面,替換其他頁面。
如果對沒有進行映射的虛擬內存地址進行讀寫操作,那么將會發生 缺頁異常。Linux 內核會對 缺頁異常 進行修復,修復過程如下:
- 獲取觸發 缺頁異常 的虛擬內存地址(讀寫哪個虛擬內存地址導致的)。
- 查看此虛擬內存地址是否被申請(是否在 brk 指針內),如果不在 brk 指針內,將會導致 Segmention Fault 錯誤(也就是常見的coredump),進程將會異常退出。
- 如果虛擬內存地址在 brk 指針內,那么將此虛擬內存地址映射到物理內存地址上,完成 缺頁異常 修復過程,並且返回到觸發異常的地方進行運行。
Mmap
mmap是用來建立從虛擬空間到磁盤空間的映射的,可以將一個虛擬空間地址映射到一個磁盤文件上,當不設置這個地址時,則由系統自動設置,函數返回對應的內存地址(虛擬地址),當訪問這個地址的時候,就需要把磁盤上的內容拷貝到內存了,然后就可以讀或者寫,最后通過manmap可以將內存上的數據換回到磁盤,也就是解除虛擬空間和內存空間的映射,這也是一種讀寫磁盤文件的方法,也是一種進程共享數據的方法 共享內存