C/C++ 內存管理算法與實現--第一章:地址線和總線 (翻譯連載)
第四節:Intel奔騰CPU構架
你已經了解處理器如何從內存讀入和寫入數據。然而,大多數的處理器同樣支持兩種高級內存管理機制:分段和分頁。所謂分段是指將計算機的地址空間劃分為特定的區域。使用分段技術可以將內存劃分為獨立的區域,這樣應用程序之間彼此獨立不會產生沖突。分段提供了內存保護的機能。可以創建不帶內存保護的內存段,但是這樣做并不會帶來什么好處。
分段結構帶來的內存保護使得每個應用程序都至少分配到一個內存段。大型的應用程序通常具有好幾個內存段。此外操作系統同樣具有一系列屬于自己的特定內存
段。這些系統的內存段設置了讀寫的權限明細,以便創建關于誰可以獲得讀寫權限的策略。一般說來,操作系統的代碼段以最高權限執行,應用程序裝載到較低權限
的內存段中。

圖1.5
分頁是實現虛擬內存的方法之一。由DRAM提供的物理內存和從硬盤分配用于模擬DRAM的內存一起合并為一個更大的集合內存空間。如果啟動了分頁機制,處理器的可尋址的最大字節數稱之為虛擬內存地址空間。要弄明白這一切的關鍵是:虛擬內存地址空間中的字節的地址不再跟之前處理器放置在地址總線上的地址一樣了。這意味著,必須創建轉換數據結構和轉換代碼,以便將虛擬地址空間里的字節映射到物理內存的一個字節上。(不必關心數據是保存在DRAM還是硬盤上)
當必須的分頁構造完畢,虛擬內存空間便劃分為了稱為頁面(pages)的小區域。操作系統會判定物理內存中運行使用機率低的數據,將這些物理內存中的數據
以分頁的形式寫入到硬盤中。如果分段機制被啟用,薄記(bookkeeping)還要執行給定內存頁與該內存頁所屬的分段的關聯記錄工作。所有的計算
工作都緊密與處理器相關,所以性能損耗跟硬盤的I/O有直接聯系,可能會持續甚至1分鐘。
圖1.6
注釋:當內存頁保存在物理內存(例如,DRAM)中時,這些內存頁放置在被稱為頁幀(Page frame)用于記錄頁面大小的結構中。除了對所有內存頁的使用情況進行監控外,大多數操作系統同樣也對頁幀的使用情況進行監控。通常頁幀的數量大大少于內存頁的數量,所以操作系統非常看重小心的對這些寶貴的資源進行管理。
注釋:可以使用不用硬盤的分頁機制。但是在這種情況下,分頁被轉變為4KB內存大小的分段。
因為很容易得到Intel Pentium的處理器
,所以我決定以Pentium處理器來講解分段和分頁機制
。我
喜歡用MIPS64處理器來闡述理論,但是我買不起SGI的服務器(唉)。廉價是Intel系列產品常勝不衰的主要原因之一。像我這樣的在1980年時候
買不起Apple
IIe電腦的計算機癡迷者,都轉而去尋覓二手的Intel機箱。成千上萬的人不得不因為資金的考慮做出這樣的選擇。所以某種意義上來說,Intel產品廣
泛使用跟基層使用者的推動不無關系。
Pentium系列處理器一直以來都是流行處理器
:
CPU 發布日期 物理地址空間
8086 1978 1MB
8088 1979 1MB
80286 1982 16MB
80386 1985 4GB
80486 1989 4GB
Pentium 1993 4GB
Pentium Pro 1995 64GB
Pentium II 1997 64GB
Pentium III 1999 64GB
Pentium 4 2000 64GB
注釋:當
1981年IBM
PC誕生的時候,搭載了一顆主頻為4.77MHz的8088CPU。毫無疑問,大型機上開發人員們欣喜若狂。因為PC給了他們一個屬于自己的施展空間了。
在那個時候,標準的啞終端除了向大型機來回傳輸緩沖區里的數據什么也干不了。不僅如此,工程師也無法對他們的代碼的運行時間和運行方式有絲毫的控制能力。
只能痛苦的等待。Tom Petty說得沒錯,偶爾用PIZZA賄賂下系統管理員,可以讓程序運行得快一些,但是這種奉承很快讓人感覺疲憊。有了IBM
PC以后工程師終于用于了屬于自己的機器,擁有一切權利,不再需要任何等待。
題外話
我認識一個CDC的工程師,也正是因為PC帶給程序員的諸多好處,他在1982年將FORTRAN '77移植到PC。他的頭走到他身邊問道:“你為什么想在小三輪車一樣的機器上運行代碼,而不是功能強大的大型機上”,他回答:“因為它是我的自己的”這段話或許概括了個人電腦(PC)大獲成功的原因所在。
為了留住老客戶,Intel為此跨域了重重困難使他們32位處理器能夠向后兼容16位的處理器構架。Intel成功的做到了這一點,我能夠在我的電腦上使用啟動盤啟動DOS 6.22系統,并且運行大多數老的DOS應用程序(包括Doom和Duke Nukem)。
Pentium處理器是一種運行在幾種不同的工作模式下實現后兼容需求的產品。各個運行模式指定各自不同的處理器如何解釋運行機器指令如何訪問內存的方式。Pentium具有四種運行模式。
-
Real mode 實模式
-
Protected mode 保護模式
-
System management mode(SMM) 系統管理模式
-
Virtual 8086 mode 虛擬8086模式
系統管理模式和虛擬8086模式都是特定目的運行模式,只在特定的環境下使用。我的焦點將主要集中在兩個運行模式上:實模式和保護模式。此外,我會對它們如何支持分段和分頁機制的部分進行深入。
具備不同的運行模式的特性的這種技術并不僅僅限于 Intel平臺。例如,MIPS64處理器同樣可以工作在四種運行模式下。
-
Kernel mode 內核模式
-
User mode 用戶模式
-
Debug mode 調試模式
-
Supervisor mode 管理員模式
實模式
第一臺IBM PC完全運行在實模式下。而且所有的32位Intel計算機同樣在啟動的時候運行于實模式下。這是實現向后兼容的必須要具備的最基本的特性。
運行在實模式下的操作系統都非常小(小于128KB)。因為它們都依靠BIOS提供的硬件接口。使得它們可以輕易的適應1.44MB的軟盤。病毒保護的修復盤依據這個事實,系統修復盤也是同樣道理。我也買過可運行在啟動盤中那種分區軟件。
在實模式中,我們在圖1.2中所見到過的通用寄存器被截取為16位的寄存器,錯誤標志寄存器和指令指針寄存器也被截取為16位。實模式寄存器結構如圖1.7所示。
圖1.7
正
如你看到的,寄存器名字前面的'E'前綴被拿掉了。此外,每一個16位的通用寄存器,AX,CX,DX,和EX,可以作為兩個8位寄存器來使用。例
如,AX寄存器可以可做是由AH和AL寄存組合而成的。AH寄存器是AX寄存器的高字節部分,AL寄存器是AX的低字節部分。
注釋:在圖1.2中的內存和模式寄存器在實模式中還是可見的。32位CPU在實模式中依然是32位的,但是它們對于實模式來說沒有任何意義和用處。除非你切換到保護模式當中。
實模式中計算機可尋址1M的DRAM。這暗示實模式中只使用了20條地址線。對于運行在實模式中的處理器來說,內存中字節的地址由段地址加上一個偏移量地
址組成。其結果總是一個20位地址值(記住這個事實:這點非常重要)這就打消了是否真的使用20條地址線的疑問。由段地址和偏移地址的和組成的地址值,便
符合了處理器的地址線上的值。現在你可以得到了為什么叫它為“實模式”的更好解釋。實模式中字節的地址直接映射到物理內存中一個“真實”的字節。
在Intel匯編語言中,地址由一個"段地址:偏移地址(segment:offset)" 的值對來表示。例如,如果一個字節位于段地址為0x8200,偏移地址為0x0100,該字節的地址值就表示為:
0x8200:0x0100
有時候,由于某些原因(一會給出解釋),也可以寫為:
0x8200[0]:0x100
實模式中內存地址解析過程如圖1.8:
圖1.8
段地址表示一個特定的內存段,并且總是保存在一個16位的段寄存器中。特別的,段地址指基地址,內存段的最低地址。各個段寄存器都各自具有特定用途:
寄存器 作用
CS 當前執行代碼的段地址
SS 堆棧段地址
DS 數據段地址
ES 額外段地址(通常作為數據段地址)
FS 額外段地址(通常作為數據段地址)
GS 額外段地址(通常作為數據段地址)
注釋:實際當中的具有6個寄存器的意思是:在任何時候,只能控制6個寄存器。一個程序可以獲得大于6個以上的寄存器,但是在任何一刻只有6個寄存器可以訪問。
偏移地址可以保存在16位的通用寄存器中。提供一個16位的偏移地址,這將每個內存段限制在64KB的大小以內。
問題:1.如果段地址和偏移地址都存儲在16位的寄存器中,為什么兩個16位值的和卻得到的是20位的值
答案:原因是段地址的末尾被添加了一個隱含的0,處理器將段地址0x0c00被處理為0x0c000。這表示,在實際書寫中,要將這個隱含0放置到方括號中。(例如,0x0c00[0])這就是為什么處理器得到20位的地址值。
正如你所見,實模式的 段地址/偏移地址 提供了一種簡單的分段機制。但是,它沒有提供我說提到過的內存段邊界保護的機制。糟糕的事實是在實模式中沒有提供任何內存保護。
當你的程序運行在實模式中,它擁有了一切,甚至可以破壞一切。
在實模式中運行應用程序就好象讓一群童子軍到你家,他們精力充沛,活力十足,隨著你手中的糖果蹦上竄下。如果你不小心,他們會把房子毀掉。將一臺運行在實模式中的機器崩潰非常容易,而且你沒有太多辦法防止它發生。(除了不斷的備份你的工作)
如果你對上述內容疑惑,我肯定有一些人一定存在同樣的疑惑,這里有個C程序代碼的例子可以使運行在實模式下的機器崩潰:
/* --crashdos.c-- */
Intel處理器如果僅僅依靠這種米老鼠玩具一樣的內存管理,將毫無作為。為了力圖支持更加健壯的操作系統和更大的內存地址空間,Intel推出了80386CPU,80386具備4GB的物理地址空間并且支持一個全新的運行模式:保護模式。