核心模式驅動

Windows系統中兩種基本驅動程式之一,它的特點是:1、核心模式驅動程式將在執行其他應用程式代碼(包括受保護的子系統代碼)的非特權處理器模式中運行。除非用戶模式驅動程式調用 Win32 API,否則將無法獲取對系統數據的訪問權。2、核心模式驅動程式將作為作業系統的執行部分(即支持一個或多個受保護的子系統的基礎作業系統組件)運行。大多數設備驅動程式將在核心模式中運行。核心模式驅動程式可執行某些受保護的操作,並可訪問用戶模式驅動程式無法訪問的系統結構。但隨著訪問權的增加,調試難度和系統損害幾率也隨之增大。

基本介紹

  • 中文名:核心模式驅動
  • 性質:Windows系統中基本驅動程式之一
  • 特點:將作為作業系統的執行部分運行等
  • 分類虛擬設備驅動程式、列印驅動程等
定義,主要組成部分,分類,驅動程式,

定義

Intel x86體系結構的處理器定義了4個級別的許可權(稱為Ring),Windows系統使用了Ring0(供特權模式使用)和Ring3(供用戶模式使用),Windows系統只使用了2個級別的許可權級別的原因是為了和其他一些硬體系統兼容,這些硬體系統只有2個級別的許可權,如Compaq Alpha和Silicon Graphics MIPS等。
每個用戶模式的進程有其私有的地址空間,這些進程在最低的許可權級別下運行(稱為Ring3或者用戶模式),它們不允許執行CPU的特權指令,對系統所屬的數據、地址空間以及硬體等的訪問也是被嚴格限制的,例如,如果某個用戶程式訪問4G地址空間中的高位2G,那么系統就會立即將其終止執行。要注意的是,進程調用系統功能的時候,可以切換到核心模式執行,但是調用結束後,就返回到用戶模式了。
用戶模式的進程總是被認為是對作業系統穩定性的潛在威脅,所以它們的許可權被嚴格地限制,任何觸及這些限制的舉動都將使進程被終止。
而核心模式的組件則可以共享這些受保護的核心模式記憶體空間,在特權級別下運行(也稱為Ring0),允許執行任何CPU指令,包括特權指令,可以無限制地訪問系統數據、代碼和硬體資源。
核心模式代碼運行在系統地址空間中,並總是被認為是可信任的,一旦被裝載運行後,驅動程式就是系統的一部分,可以無限制地做任何事情。
總的來說,用戶模式程式被完全從作業系統隔離,這對作業系統的完整性來說是件好事情,但對某些種類的應用程式來說就太頭痛了,比如Debug工具。幸運地是,這些在用戶模式幾乎不可能完成的任務完全可以通過核心模式的驅動程式來完成,因為這些驅動程式的操作是不受限制的。因此,如果你打算從用戶模式存取作業系統內部的數據結構或者函式的話,唯一的方法就是將一個核心模式驅動程式裝載到系統的地址空間中(並調用它),這是很簡單的事情,作業系統完全支持這樣的操作。

主要組成部分

根據地址空間、代碼許可權和職責的不同,Windows NT內部劃分為兩個截然不同的部分。
地址空間的享用方式也非常容易理解,整個32位系統的4GB內容被劃分為兩個相等的部分,用戶模式(user-mode)的進程使用的地址空間被映射到低位的2GB上(地址範圍00000000 - 7FFFFFFFh),而高位的2GB(地址範圍80000000h - 0FFFFFFFFh)則供作業系統的組成部分來使用,如設備驅動程式、系統記憶體池、系統使用的數據結構等,在這部分中,記憶體共享的許可權和職責等方面就要複雜一點了。
下面就是用戶模式進程的一些簡單分類:
◎ 系統支持進程--如Logon進程(位於\%SystemRoot%\System32\Winlogon.exe)
◎ 服務進程--如Spooler進程(位於\%SystemRoot%\System32\spoolsv.exe
◎ 用戶應用程式--任何Win32、Windows 3.1、DOS、POSIX或者OS/2程式
◎ 子系統--Windows內置3個子系統:Win32(位於\%SystemRoot%\System32\Csrss.exe)、POSIX子系統(位於\%SystemRoot%\System32\Psxss.exe)和OS/2子系統(位於\%SystemRoot%\System32\Os2ss.exe),在Windows XP以及後續的作業系統中,POSIX和OS/2子系統已經被去掉了。
而下面是核心模式的一些模組:
◎ 運行模組--記憶體管理、進程和執行緒的管理、安全機制等
◎ 核心--執行緒調度、中斷、異常的分派等(運行模組和核心位於\%SystemRoot%\System32\Ntoskrnl.exe
◎ 設備驅動程式--硬體設備驅動程式、檔案系統和網路驅動程式
硬體抽象層(Hardware Abstraction Layer, HAL)--將核心、設備驅動程式和運行模組和具體的硬體平台隔離開(位於\%SystemRoot%\System32\Hal.dll
◎ 視窗和圖形系統--實現GUI函式,如處理視窗、用戶界面的控制和繪畫等(位於\%SystemRoot%\System32\Win32k.sys)

分類

Windows NT支持的設備驅動程式的範圍很廣,它們的分類如下:
用戶模式的驅動程式
虛擬設備驅動程式(Virtual Device Drivers/VDD)--用戶模式的組件,用於為16位的MS-DOS應用程式提供虛擬的執行環境,雖然和Windows 95/98裡面的VxD從功能上看起來是差不多的,但實際上兩者根本不同。
列印驅動程式--將與設備無關的圖形轉換到和印表機相關的指令
核心模式驅動程式:
◎ 檔案系統驅動程式--實現標準的檔案系統模型
◎ 傳統設備驅動程式--用於在沒有其他驅動程式幫助的情況下控制硬體設備,它們是為老版本的Windows NT系統所寫的,但是也可以不加修改地運行在Windows 2000/XP/2003系統上
視頻驅動程式--不用多介紹了吧?
◎ 流驅動程式--支持多媒體設備,如音效卡
◎ WDM驅動程式--即Windows Driver Model,WDM包括對Windows NT電源管理即插即用的支持,WDM可以在Windows 2000、Windows 98和Windows ME下實現,所以在這些作業系統下,WDM驅動程式在原始碼級別是兼容的,在有些情況下,在二進制代碼級別上也是兼容的
在不同的資料中,對驅動程式的分類方法可能完全不同,但這並不是問題。
從名稱理解,設備驅動程式是用於控制某個設備的,但這個"設備"並不一定指的是物理上存在的設備,它也可以是虛擬設備
從檔案結構上講,設備驅動程式就是一個普普通通的PE格式檔案,就像其他EXE或者DLL檔案一樣。設備驅動程式是一個可裝載的核心模式模組,一般以SYS為擴展名。他們之間的不同點在於兩種的裝載方法是完全不同的。實際上,我們可以把設備驅動程式理解成一個核心模式的DLL,用於完成在用戶模式下所不能完成的功能,本質上的不同就在於我們無法直接存取設備驅動程式的代碼和數據(註:DLL的代碼和數據是可以被直接存取的,這方面的資料可以參考《Windows環境下32位彙編語言程式設計一書》中的DLL一章),唯一的存取方式是通過I/O管理器,它提供了簡單的驅動程式管理環境。
剛開始學習KMD的開發的時候,你可能感覺自己根本就是一個菜蟲(旁白:就是比菜鳥還低級,呵呵~~~),因為你以前用Windows API開發程式的經驗在這裡根本幫不上忙,即使你以前寫過n多個(n趨向無窮大……)用戶模式下的套用系統也沒用。核心提供了完全不同的函式和數據結構,以至於你要從頭開始了解,而且資料奇缺無比,一般情況下,可供參考的只有頭檔案。

驅動程式

大部分控制硬體設備的驅動程式是分層的驅動程式,分層驅動的概念就是當用戶模式發出一個請求時,每個請求從高層次的驅動程式逐層處理並流傳到低層次的驅動程式中,一個I/O請求的處理可能分步在多個驅動程式中,例如,如果一個應用程式發出讀盤請求,處理請求會在多個驅動程式中流過,在其中你也可以再加入n多個過濾驅動程式(比如插入一個加解密的模組)。
單層的驅動程式是最簡單的一類驅動程式,這一類驅動程式通常並不依賴於其他已裝載的驅動程式,他們的接口僅僅針對用戶模式的應用程式,開發和調試這一類驅動程式是非常簡單的,我們即將開始討論的就是這類程式,其他類型的驅動程式將在以後討論。
在大多數情況下,我們的系統中只安裝了一個CPU,所以,對於所有這些運行中的程式來說,作業系統對每個進程中的執行緒所使用的CPU時間進行調度,循環為每個執行緒分配時間片,這就造成了多個程式同時執行的假象。如果系統中安裝了多個CPU,那么作業系統的調度算法將複雜得多,因為它要將各CPU上的執行緒進行平衡。如果Windows檢測到一個新執行緒要開始運行了,它將進行一次上下文切換(context switch)(註:上下文(Content)實際上就是執行緒運行的環境,也就是運行時各暫存器和其他東東的狀態,更自然的理解就是"執行緒狀態")。所謂上下文切換就是保存執行緒運行時的機器狀態,然後將另一個執行緒的狀態恢復並重新開始執行。如果重新開始執行的執行緒屬於另一個進程,那么該進程的地址空間也將被同時切換過來(通過在CR3暫存器中裝入頁表)。
每個用戶進程都有私有的地址空間,所以他們的頁表都是不同的,CPU通過切換頁表來將虛擬地址映射到物理地址,設備驅動程式並不需要直接做這些工作。上下文切換比較耗CPU時間,所以驅動程式一般不創建它們自己的執行緒,它們一般在下列環境中的一個中運行:
1. 在發起I/O請求的用戶執行緒中運行
2. 在核心模式下的系統執行緒中運行
3. 作為中斷運行(並不處於哪個特定的進程或執行緒中,因為它們都被暫時掛起了)
在處理I/O請求包(IRPs)時,我們總是運行在和用戶模式的調用者相同的進程上下文中運行,這樣我們就能對用戶程式地址空間進行定址。但是當驅動程式被載入或者卸載的時候,我們將在系統進程中運行,這時存取的只能是系統的地址空間。
中斷是任何作業系統都少不了的組成部分,中斷使處理器打斷正常的程式流程來首先處理它們,中斷分硬體中斷和軟體中斷兩種,中斷是分優先權的,一個高優先權的中斷可以打斷低優先權的中斷的執行。
Windows中把中斷優先權稱為IRQLs(interrupt request levels),在系統中表示為從0(被動)到31(高級)的整數,其中大的數值對應高優先權的中斷。注意IRQL值的含義和執行緒調度優先權的含義是完全兩碼事情。
嚴格來說,IRQL=0的中斷並不是中斷,因為它無法打斷任何其他代碼的執行(因為沒有比0更低級的代碼了),所有的用戶模式執行緒在這個級別上運行,該級別也稱為被動級別(passive level)。我們後面要討論的驅動程式代碼也在這個級別上運行,注意這並不意味著其他的驅動程式也在被動級別下運行。
因此這裡還有兩個重要的結論:
首先:當驅動程式運行於用戶模式程式的執行緒中時,代碼的執行可能被高IRQL級別的代碼打斷,一些函式可以用來獲取當前的IRQL值,並可以對其進行提升或者降低。
第二:被動模式IRQL下的代碼可以調用任何的核心函式(DDK指明了每個函式允許調用的IRQL級別),可以對已分頁的或未分頁的記憶體進行定址(註:即已映射過的虛擬地址還是物理記憶體地址)。反過來,當在一個比較高的IRQL級別下對分頁記憶體進行定址時(指等於或高於DISPATCH_LEVEL),系統將崩潰,因為這時記憶體管理器的IRQL級別反而比較低,以至於無法處理頁錯誤了。
我想每個人都見過著名的藍屏當機畫面,即"Blue Screen Of Death",簡稱為BSOD,也許根本不需要解釋它是怎么出現或者在什麼時候出現的,因為在後面的KMD開發過程中,你會很頻繁地遇到它們。
核心模式下,Windows不對任何系統記憶體進行保護,由於核心模式的驅動程式可以對系統記憶體和作業系統的地址空間進行任意存取,所以你必須對你開發的驅動程式進行嚴格的測試,以防它危及到系統的穩定。
你可以把這個作為最基本的原則,另外,如果沒有執行緒上下文、中斷優先權、核心模式和用戶模式等方面的概念,開發核心模式驅動程式將是不可能的事(天哪,到現在我才發現,我連菜蟲都算不上,我竟然是~~~~~~菜菜的單細胞生物!嗚嗚~~)
Windows DDK是MSDN專業版和宇宙版的一部分,它也可以從microsoft.com ddk 下載,對於開發設備驅動程式來說,DDK是關於Windows NT內部信息,包括系統函式數據結構等的豐富資源,不幸的是,微軟已經停止了免費發放DDK,所以現在只好去買正版的CD了(沒有槍,沒有炮,盜版游擊隊給我們造~~~)
除了文檔,DDK還包含了一堆的庫檔案(*.lib),這些庫可以在連結的時候用上。這些庫有兩種版本:普通的版本(稱為free build)和特殊的包含Debug信息的版本(稱為checked build),它們分別位於%ddk%\libfre\i386和%ddk%\libchk\i386目錄下,check build是在編譯Windows原始碼時加上DEBUG標誌後生成的,在開發驅動程式時,它們可以提供更加精確的錯誤定位,但是你首先要根據你的作業系統選擇合適的lib版本才行。
KmdKit包含了所有用彙編開發KMD所需要的東西:include檔案、lib檔案宏定義、例子檔案、工具和一些文章,你可以自己在軟體包中找到更多的東西,下一節我們將從這個軟體包中包括的一些例子開始學習KMD的編程。
調試核心模式的代碼需要合適的調試器,Compuware的SoftIce是個不錯的選擇(見compuware.com products numega index.htm),當然你也可以使用Microsoft Kernel Debugger,它需要兩台計算機:主機和目標機器,目標機器是被調試的機器,主機是運行調試軟體的機器。Mark Russinovich ( sysinternals.com ) 也寫了一個工具,叫做LiveKd,它允許在單台機器上運行Microsoft Kernel Debugger,而不再需要兩台機器了。

相關詞條

熱門詞條

聯絡我們