Linux 的內存分頁管理

內存是計算機的主存儲器。內存爲進程開闢出進程空間,讓進程在其中保存數據。我將從內存的物理特性出發,深入到內存管理的細節,特別是瞭解虛擬內存和內存分頁的概念。

內存

簡單地說,內存就是一個數據貨架。內存有一個最小的存儲單位,大多數都是一個字節。內存用內存地址(memory address)來爲每個字節的數據順序編號。因此,內存地址說明了數據在內存中的位置。內存地址從0開始,每次增加1。這種線性增加的存儲器地址稱爲線性地址(linear address)。爲了方便,我們用十六進制數來表示內存地址,比如0x00000003、0x1A010CB0。這裏的“0x”用來表示十六進制。“0x”後面跟着的,就是作爲內存地址的十六進制數。

內存地址的編號有上限。地址空間的範圍和地址總線(address bus)的位數直接相關。CPU通過地址總線來向內存說明想要存取數據的地址。以英特爾32位的80386型CPU爲例,這款CPU有32個針腳可以傳輸地址信息。每個針腳對應了一位。如果針腳上是高電壓,那麼這一位是1。如果是低電壓,那麼這一位是0。32位的電壓高低信息通過地址總線傳到內存的32個針腳,內存就能把電壓高低信息轉換成32位的二進制數,從而知道CPU想要的是哪個位置的數據。用十六進制表示,32位地址空間就是從0x00000000 到0xFFFFFFFF。

內存的存儲單元採用了隨機讀取存儲器(RAM, Random Access Memory)。所謂的“隨機讀取”,是指存儲器的讀取時間和數據所在位置無關。與之相對,很多存儲器的讀取時間和數據所在位置有關。就拿磁帶來說,我們想聽其中的一首歌,必須轉動帶子。如果那首歌是第一首,那麼立即就可以播放。如果那首歌恰巧是最後一首,我們快進到可以播放的位置就需要花很長時間。我們已經知道,進程需要調用內存中不同位置的數據。如果數據讀取時間和位置相關的話,計算機就很難把控進程的運行時間。因此,隨機讀取的特性是內存成爲主存儲器的關鍵因素。

內存提供的存儲空間,除了能滿足內核的運行需求,還通常能支持運行中的進程。即使進程所需空間超過內存空間,內存空間也可以通過少量拓展來彌補。換句話說,內存的存儲能力,和計算機運行狀態的數據總量相當。內存的缺點是不能持久地保存數據。一旦斷電,內存中的數據就會消失。因此,計算機即使有了內存這樣一個主存儲器,還是需要硬盤這樣的外部存儲器來提供持久的儲存空間。

虛擬內存

內存的一項主要任務,就是存儲進程的相關數據。我們之前已經看到過進程空間的程序段、全局數據、棧和堆,以及這些這些存儲結構在進程運行中所起到的關鍵作用。有趣的是,儘管進程和內存的關係如此緊密,但進程並不能直接訪問內存。在Linux下,進程不能直接讀寫內存中地址爲0x1位置的數據。進程中能訪問的地址,只能是虛擬內存地址(virtual memory address)。操作系統會把虛擬內存地址翻譯成真實的內存地址。這種內存管理方式,稱爲虛擬內存(virtual memory)。

每個進程都有自己的一套虛擬內存地址,用來給自己的進程空間編號。進程空間的數據同樣以字節爲單位,依次增加。從功能上說,虛擬內存地址和物理內存地址類似,都是爲數據提供位置索引。進程的虛擬內存地址相互獨立。因此,兩個進程空間可以有相同的虛擬內存地址,如0x10001000。虛擬內存地址和物理內存地址又有一定的對應關係,如圖1所示。對進程某個虛擬內存地址的操作,會被CPU翻譯成對某個具體內存地址的操作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章