對于Windows操作系統(tǒng)的編程一般來說已經(jīng)涉及到了較深的領(lǐng)域,針對該問題提出幾家之言,均為轉(zhuǎn)載:
一、
為了防止用戶程序訪問并篡改操作系統(tǒng)的關(guān)鍵部分,Windows使用了2種處理器存取模式(事實上Windows運行的處理器可以支持4種模式):用戶模式和內(nèi)核模式。用戶程序運行在用戶模式而操作系統(tǒng)代碼(如系統(tǒng)服務(wù)和設(shè)備驅(qū)動程序)則運行在內(nèi)核模式。在內(nèi)核模式下程序可以訪問所有的內(nèi)存和硬件,并使用所有的處理器指令。操作系統(tǒng)程序比用戶程序有更高的權(quán)限,使得系統(tǒng)設(shè)計者可以確保用戶程序不會意外的破壞系統(tǒng)的穩(wěn)定性。
雖然Windows進程有自己的運行空間,但是內(nèi)核模式的操作系統(tǒng)代碼和設(shè)備驅(qū)動程序代碼則運行在同一個虛擬地址空間。虛擬內(nèi)存中的每一頁都標明了他可由處理器以哪種方式訪問。系統(tǒng)空間中的也只能在內(nèi)核模式下訪問,而用戶空間中的也在任何模式下都可以訪問。而只讀頁(如可執(zhí)行代碼)在任何模式下都不能被寫入。
Windows對運行在內(nèi)核模式組件的空間并不提供讀/寫保護,這意味著在內(nèi)核模式下,操作系統(tǒng)和驅(qū)動程序代碼可以進入系統(tǒng)空間,并繞過系統(tǒng)的安全機制而訪問對象。因為Windows的大部分運行在內(nèi)核模式,因此在設(shè)計內(nèi)核程序時要特別的謹慎,防止他們破壞系統(tǒng)的安全。
以上問題也說明在用第三方的驅(qū)動程序時也要很小心,因為一旦驅(qū)動程序運行在內(nèi)核模式他就可訪問系統(tǒng)的所有數(shù)據(jù)。這也是在Windows中進入驅(qū)動程序簽證的一個原因,即當用戶使用未注冊的第三方軟件時系統(tǒng)會給出警告。一個叫做驅(qū)動檢測(Driver Verifier)的機制可以幫助驅(qū)動開發(fā)者發(fā)現(xiàn)bug(如緩存溢出和內(nèi)存泄漏)。
用戶程序在調(diào)用一個系統(tǒng)服務(wù)時會轉(zhuǎn)入內(nèi)核模式,比如Windows的ReadFile函數(shù)最終會調(diào)用內(nèi)部的一個例程,后者實際執(zhí)行了讀文件,因為他要訪問系統(tǒng)數(shù)據(jù),因此它必須允許在內(nèi)核模式。從用戶模式向內(nèi)核模式的轉(zhuǎn)換是由一個特殊的指令完成的。操作系統(tǒng)捕獲了這個指令,通知系統(tǒng)要請求一個服務(wù),并將線程的參數(shù)傳遞給系統(tǒng)函數(shù)從而執(zhí)行內(nèi)部的函數(shù)功能。在將控制權(quán)將給線程之前,處理器會轉(zhuǎn)回到用戶模式,這樣操作系統(tǒng)可以防止它的數(shù)據(jù)被誤讀或誤寫。
注意,從用戶模式向內(nèi)核模式的轉(zhuǎn)換并不會影響線程的調(diào)度,事實上,模式的轉(zhuǎn)換并不意味著運行環(huán)境的改變。
因此一個用戶線程事實上一部分時間在用戶模式下運行,另一部分時間在內(nèi)核模式下運行。由于圖畫和窗口系統(tǒng)也在內(nèi)核模式下,因此畫圖較多的程序在內(nèi)核模式下的運行時間回比用戶模式下更多。比如你可以允許一個Windows的圖畫本,或者彈球游戲,并觀察他們分別在用戶模式和內(nèi)核模式下的時間。
可以用Windows自帶的性能工具察看。通過開始-程序-管理工具-性能打開,或者在控制面板里面打開,管理工具-性能。
二、
從Intel80386開始,出于安全性和穩(wěn)定性的考慮,該系列的CPU可以運行于ring0~ring3從高到低四個不同的權(quán)限級,對數(shù)據(jù)也提供相應(yīng)的四個保護級別。運行于較低級別的代碼不能隨意調(diào)用高級別的代碼和訪問較高級別的數(shù)據(jù),而且也只有運行在ring0層的代碼可以直接對物理硬件進行訪問。由于WindowsNT是一個支持多平臺的操作系統(tǒng),為了與其他平臺兼容,它只利用了CPU的兩個運行級別。一個被稱為內(nèi)核模式,對應(yīng)80x86的ring0層,是操作系統(tǒng)的核心部分,設(shè)備驅(qū)動程序就是運行在該模式下;另一個被稱為用戶模式,對應(yīng)80x86的ring3層,操作系統(tǒng)的用戶接口部分(就是我們通常所說的win32 API)以及所有的用戶應(yīng)用程序都運行在該級別。操作系統(tǒng)對運行在內(nèi)核模式下的代碼是不設(shè)防的,所以不管是建設(shè)還是破壞內(nèi)核模式下的編程都是值得去研究的。
如下圖所示為Windows操作系統(tǒng)驅(qū)動程序模型:
Windows驅(qū)動程序既可以運行在用戶態(tài)也可以運行在核心模態(tài)。
用戶態(tài)與核心太驅(qū)動程序的區(qū)別
用戶態(tài)的驅(qū)動程序運行在非特權(quán)處理機模式(nonprivileged processor mode)上,其他一些被保護的子系統(tǒng)代碼也運行在該模式上。用戶態(tài)的驅(qū)動程序不能獲得系統(tǒng)數(shù)據(jù)的存取權(quán),除非調(diào)用Win32 API或者系統(tǒng)服務(wù)。
核心態(tài)驅(qū)動程序作為操作系統(tǒng)的一個組成部分被執(zhí)行——支持一個或多個受保護的子系統(tǒng)的操作系統(tǒng)底層組件。
用戶態(tài)和核心態(tài)驅(qū)動程序有不同的結(jié)構(gòu),不同的入口點和不同的系統(tǒng)接口。一個設(shè)備是需要一個用戶態(tài)驅(qū)動程序還是需要一個核心態(tài)驅(qū)動程序依賴于該設(shè)備的類型和操作系統(tǒng)對它提供的支持。
一些設(shè)備驅(qū)動程序可以完全地或部分地運行在用戶態(tài)。用戶態(tài)驅(qū)動程序沒有堆??臻g的限制,可以訪問Win32 API,并且容易調(diào)試。
大多設(shè)備驅(qū)動程序運行在核心態(tài)。核心態(tài)驅(qū)動程序可以完成某些受保護的操作,并且可以訪問用戶態(tài)驅(qū)動程序不能訪問的系統(tǒng)結(jié)構(gòu)體(system sturcture)。然而,訪問權(quán)限的提高當然也要付出相應(yīng)的代價——調(diào)試的艱難,系統(tǒng)隨時面臨毀壞的危險。當代碼運行在有特權(quán)的核心態(tài)環(huán)境中時,操作系統(tǒng)對代碼所請求的數(shù)據(jù)的完整性和有效性的檢查將大大減少。
為了方便,應(yīng)該用高級語言(high-level language)來編寫驅(qū)動程序,通常,C適合用來編寫核心態(tài)驅(qū)動程序,C或C++則適合用于編寫用戶態(tài)驅(qū)動程序。
用戶模式與內(nèi)核模式是如何交互的呢
當用戶模式程序需要讀取設(shè)備數(shù)據(jù)時,它就調(diào)用Win32 API函數(shù),如ReadFile。Win32子系統(tǒng)模塊(如KERNEL32.DLL)通過調(diào)用平臺相關(guān)的系統(tǒng)服務(wù)接口實現(xiàn)該API,而平臺相關(guān)的系統(tǒng)服務(wù)將調(diào)用內(nèi)核模式支持例程。在ReadFile調(diào)用中,調(diào)用首先到達系統(tǒng)DLL(NTDLL.DLL)中的一個入口點,NtReadFile函數(shù)。然后這個用戶模式的NtReadFile函數(shù)接著調(diào)用系統(tǒng)服務(wù)接口,最后由系統(tǒng)服務(wù)接口調(diào)用內(nèi)核模式中的服務(wù)例程,該例程同樣名為NtReadFile。
系統(tǒng)中還有許多與NtReadFile相似的服務(wù)例程,它們同樣運行在內(nèi)核模式中,為應(yīng)用程序請求提供服務(wù),并以某種方式與設(shè)備交互。它們首先檢查傳遞給它們的參數(shù)以保護系統(tǒng)安全或防止用戶模式程序非法存取數(shù)據(jù),然后創(chuàng)建一個稱為“I/O請求包(IRP)”的數(shù)據(jù)結(jié)構(gòu),并把這個數(shù)據(jù)結(jié)構(gòu)送到某個驅(qū)動程序的入口點。在剛才的ReadFile調(diào)用中,NtReadFile將創(chuàng)建一個主功能代碼為IRP_MJ_READ(DDK頭文件中的一個常量)的IRP。實際的處理細節(jié)可能會有不同,但對于NtReadFile例程,可能的結(jié)果是,用戶模式調(diào)用者得到一個返回值,表明該IRP代表的操作還沒有完成。用戶模式程序也許會繼續(xù)其它工作然后等待操作完成,或者立即進入等待狀態(tài)。不論哪種方式,設(shè)備驅(qū)動程序?qū)υ揑RP的處理都與應(yīng)用程序無關(guān)。
驅(qū)動程序完成一個I/O操作后,通過調(diào)用一個特殊的內(nèi)核模式服務(wù)例程來完成該IRP。完成操作是處理IRP的最后動作,它使等待的應(yīng)用程序恢復(fù)運行
聯(lián)系客服