一、理解保護模式
大多數現代作業系統(包括Windows 9X/NT/XP和Linux等)都是多工的,CPU的保護模式是作業系統實現多工的基礎。瞭解保護模式的底層原理對學習作業系統有著事半功倍的作用。
保護模式是為了實現多工而設計的,其名稱中的“保護”就是保護任務環境中各個人物的安全。多工環境的一個基本問題就是當多個任務同時執行時,如何保證一個任務不會受到另一個任務的破壞,同時也不會破壞其他任務,也就是要實現多個任務在同一個系統中“和平共處,互不侵犯”。所謂的“任務”,從CPU的角度來看就是CPU可以獨立排程和執行的程式單位。從Windows作業系統的角度來看,就是一個任務就是一個執行緒(thread)或者程序(process)。
總結來說,可以把保護模式對任務的保護機制劃分為任務內的保護和任務間的保護。任務內的保護指的是同一任務內不同級別的程式碼不會相互破壞。任務間的保護指的是一個任務不會破壞另一個任務。簡單的說,任務間的保護是靠記憶體對映機制(包括段對映和頁對映)實現的,任務內的保護是靠特權級別檢查實現的。
1.1任務間的保護機制
任務間的保護主要是靠虛擬記憶體對映機制來實現的,即在保護模式下,每個人物都被置於一個虛擬記憶體控制元件中,作業系統來決定何時以及如何把這些虛擬記憶體對映到實體記憶體。
舉例:
在Win32下,每個人物都被賦予4GB的虛擬記憶體空間,可以用地址0~0XFFFFFFFF來訪問這個空間的任意地址。雖然不同的人物可以訪問相同的地址(比如:0x00401010,但是因為這個地址僅僅是當前任務空間中的虛擬地址,不同任務處於不同的虛擬空間中,不同任務的虛擬地址被對映到不同的實體地址,這樣就可以很容易的防止一個任務內的程式碼直接訪問另一個任務的資料。IA-32 CPU提供了兩種機制來實現記憶體對映:段基址(Segmentation)和頁基址(paging)。
1.2任務內保護機制
任務內的保護機制主要用於保護作業系統。
作業系統的程式碼和資料透過被對映到系統中每個人物的記憶體空間中,並且對於所有人物其地址是一樣的。例如,在Windows系統中,作業系統的程式碼和資料通常會被對映到每個程序的高2GB空間中。這意味著作業系統的空間對於應用程式來說是“可觸及的”,應用程式中的指標可以指向作業系統中所使用的記憶體。
任務內保護的核心思想就是許可權的控制,即程式碼和資料根據其重要性指定特權級別,高特權級的程式碼可以執行和訪問低特權級的程式碼和資料,而低特權級的程式碼不可以直接執行和訪問高特權級的程式碼和資料。高特權級通常被賦予重要的資料和可信任的程式碼,比如作業系統的資料和程式碼。低特權級通常被賦予不重要的資料和程式碼,比如應用程式。這樣作業系統可以直接訪問應用程式的程式碼和資料,而應用程式雖然可以指向系統的空間,但是不能訪問,一旦訪問就會被系統發現並且禁止。
例項:
int main(int argc,char*argv[])
{
*(int*)0x8003f100 = 0x22; //檢視訪問高2GB記憶體並且賦值
return 0;
}
分析:儘管應用程式可以指向系統的記憶體,但是訪問時會被系統發現並且禁止。
事實上,應用程式只能透過系統提供的介面(API)來使用作業系統的服務,即系統呼叫。系統呼叫相當於在系統程式碼和使用者程式碼之間開了一扇有人看守的小門。
1.3特權級