既然Windows API編程是與Windows操作系統進行交互,所以就必須對Windows操作系統如何運行應用程式的原理搞清楚。 1、保護模式 操作系統是依附於cpu硬體的,所以操作系統所具備的功能也是cpu所給予的。Intel的32位CPU有兩種主要的模式:實模式和保護模式。Dos操作系統就是運 ...
既然Windows API編程是與Windows操作系統進行交互,所以就必須對Windows操作系統如何運行應用程式的原理搞清楚。
1、保護模式
操作系統是依附於cpu硬體的,所以操作系統所具備的功能也是cpu所給予的。Intel的32位CPU有兩種主要的模式:實模式和保護模式。Dos操作系統就是運行在實模式下,而現代的操作系統都是充分利用了保護模式,從而使系統大大的安全穩定了很多。現代電腦都是用的馮諾依曼體系,其核心就是記憶體。所以CPU內部有寄存器,外部有記憶體,所以所謂的實模式和保護模式其本質就是對記憶體的訪問形式不同。實模式就是對記憶體的直接訪問,比如要在屏幕上顯示一個數字就直接往顯存中寫就可以了,dos下編程就是這樣的。但這有一個最大的問題就是不安全,任何程式可以隨意訪問記憶體,很容易就和操作系統的地址衝突,所以玩過dos的人都知道電腦是很容易死機的。為瞭解決這個問題,Intel在386以後的CPU都提供了保護模式。這種模式最重要的一個應用就是虛擬記憶體地址,大家都知道32位的CPU可以定址的範圍是4GB,在虛擬記憶體中給每一個進程都分配了4GB的虛擬地址。如果同時運行10個進程就要有10個4GB的虛擬記憶體,那問題來了,哪有這麼多的記憶體呢?呵呵,所以這是虛擬記憶體嘛,不是真正的物理記憶體。只是面對進程,讓程式員可以使用的記憶體地址,比如 int * p=new int 這句話是向電腦要一個4位元組的記憶體,地址存在p裡面,要是在實模式下p裡面就是真正的物理地址,但是在保護模式下,p裡面存的只是一個虛擬地址,至於真正的物理地址是多少是不允許程式員知道的,當windows拿到p後會把p裡面的虛擬地址映射到一個物理地址中去的,而這一個過程是黑箱操作,普通的應用程式是不允許知道的。
2、內核空間和用戶空間:
好了,現在知道在保護模式下編寫程式訪問的是4GB的虛擬記憶體,但是這4GB空間也不是全部給應用程式用的,操作系統也要使用,所以Windows規定把4GB空間分成兩半,低2GB(0—0x7fffffff)空間用戶可以使用,而高2GB空間(0x80000000—0xffffffff)用戶不能使用,留給操作系統。所以這就有了用戶空間和內核空間的區別。而這個規定其實也是用了CPU的特權級的功能:內核空間是0環,用戶空間在3環,所以這就在CPU級別把內核和用戶程式分割開了,目的就是確保用戶程式不能騷擾內核,從而保證系統穩定。
3、內核對象:
但現在問題又來了,內核空間用戶不能訪問,那麼操作系統的各種功能我們怎麼調用呢?比如往屏幕上畫一條線,在實模式下很簡單,就是在顯存裡面寫一排01010101就可以了,但是在實模式下我們只能訪問2GB用戶空間,顯存在哪裡都不知道,這怎麼寫啊?很容易想到的就是操作系統幫我們找顯存的位置,我們只要調用操作系統的相關函數就可以了。但是操作系統在高2GB的內核空間中,我們還是不能直接使用。現在操作系統既要給我們用,又不能讓我們直接用,那怎麼辦呢,微軟的工程師想出的一個辦法就是給我們一個編號,也就是句柄(HANDLE),讓我們要用內核什麼功能就用句柄來用,這樣就不必讓我們知道具體的內核地址了。從而內核對象也就自然產生,Windows對硬體的所有操作都做成一個一個內核對象,我們要用的時候就申請這個對象,然後Windows給我們一個句柄,Windows內部計數器加1,我們不用了就關閉句柄,Windows內部計數器減1,當計數器為0的時候,Windows知道這個內核對象已經不用了,所以從真實物理記憶體中銷毀。對於我們應用程式員來說,我們要做的事情就是申請內核對象,拿到句柄,操作句柄,銷毀句柄。而這個流程也就是和Windows交互的流程,也就是所謂Windows編程的本質。