一、背景介紹
1.1WindowsNT操作系統的組成
1.1.1用戶模式(UserMode)與內核模式(KernelMode)
從Intel80386開始,出於安全性和穩定性的考慮,該系列的CPU可以運行於ring0~ring3從高到低四個不同的權限級,對數據也提供相應的四個保護級別。運行於較低級別的代碼不能隨意調用高級別的代碼和訪問較高級別的數據,而且也只有ring0層的代碼可以直接進行對物理硬件的訪問。由於WindowsNT是一個支持多平台的操作系統,為了與其他平台兼容,它只利用了CPU的兩個運行級別。一個被稱為內核模式,對應80x86的ring0層,操作系統的核心部分,包括設備驅動程序都運行在該模式;另一個被稱為用戶模式,對應80x86的ring3層,操作系統的用戶接口部分以及所有的用戶應用程序都運行在該級別。
1.1.2WindowsNT操作系統的結構
圖1簡要地描述了WindowsNT的系統組成。
圖一
從圖中可以看到,在物理硬件(Hardware)與系統核心(Kernel)之間有一個硬件抽象層(HardwareAbstractionLayer),它屏蔽了不同平台硬件的差異,向操作系統的上層提供了一套統一的接口。從圖中我們還可以看到,設備驅動程序(DeviceDriver)是被I/O管理器(I/OManager)包圍起來的,即驅動程序與操作系統上層的通信全部都要通過I/O管理器。這給驅動程序的編寫帶來了很大的便利,因為很多諸如接收用戶的請求、與用戶程序交換數據、內存映射、掛接中斷、同步等等麻煩的工作都由I/O管理器代勞了。
1.1.3WindowsNT設備驅動程序的分類
根據是否直接操作硬件,可以把驅動程序分成兩大類:內核模式的驅動程序和專用驅動程序。
內核模式的驅動程序根據硬件的通信協議,直接對硬件進行端口訪問、中斷響應、DMA傳輸。它包括:串、並行口,鍵盤,文件系統,SCSI,網絡等驅動程序;專用驅動程序包括視頻,打印,多媒體,虛擬DOS等驅動程序,他們在實現上與前者有很大區別。我在實習期間所做的工作以及本文以下的討論都局限於內核模式的驅動程序。
p>1.2WindowsNT下內核模式設備驅動程序的結構和運行
一般來說,設備驅動程序的任務主要有二:第一,接受來自用戶程序的讀寫請求,把用戶的數據傳送給設備,或把從設備接收到的數據傳送給用戶;第二,輪詢設備或處理來自設備的中斷請求,完成數據傳輸。
1.2.1驅動程序與用戶程序的通信
I/O管理器把每一個設備對上層都抽象成了文件,所以在Win32用戶程序中只要通過以下幾條簡單的文件操作API函數就可以實現與驅動程序中的某個設備通信(請注意,一個驅動程序可以驅動多個設備):
函數名功能
CreateFile打開一個設備,准備進行數據傳輸。返回一個與設備相關的句柄。
CloseHandle關閉一個由CreateFile打開的設備。
ReadFile從設備讀取數據。
WriteFile向設備寫數據。
DeviceIoControl對設備進行一些自定義的操作,比如更改設置等。
表一
1.2.2DriverEntry過程
這是每一個設備驅動程序的入口,每次該程序啟動時被系統自動調用。大部分的設備初始化的工作都在這個過程中完成。包括設置響應各種用戶請求的過程的入口,使I/O管理器能知道當用戶的打開、關閉、讀寫等請求到來時各應調用那些過程來處理。驅動程序中只有本過程的名字"DriverEntry"是固定的,以下列出的所有過程都要由本過程向系統注冊。
如果該驅動程序不響應任何請求的話,只要一個DriverEntry過程就可以構成一個能運行的驅動程序。
1.2.3Unload和ShutDown過程
Unload過程負責在驅動程序被停止前做一些必要的處理。比如釋放資源,記錄最終狀態等。ShutDown過程在系統即將關閉時被調用,與前者的區別在於不用釋放任何資源。
1.2.4DispatchOpen和DispatchClose過程
這兩個過程在用戶調用CreateFile和CloseHandle時被調用,為即將到來的讀寫操作做備,或做一些讀寫完成後的必要處理。
1.2.5DispatchRead,DispatchWrite與StartIo過程
這前兩個過程在用戶調用ReadFile和WriteFile時被調用。它們先做一些檢驗用戶請求合法性的工作,然後啟動一個被稱為StartIo的過程開始實際的與硬件間的數據傳輸。I/O管理器還通過IRP為它們提供了一個指向用戶緩沖區的指針,用於與用戶程序交換數 詳情請見1.3.2
1.2.6接受自定義的其他請求
這兩個過程在用戶調用DeviceIoControl時被調用。它通過IRP獲得用戶的請求號,以及一個指向用戶緩沖區的指針,可以與用戶程序進行通信。
1.2.7中斷處理過程(ISR)
這些過程在中斷發生時被系統調用。
1.2.8推遲過程(DeferredProcedure)
這些過程用來在較低的運行級別完成較高運行級別過程(如中斷處理過程)的一些任務。詳情請見1.3.3
p>1.3實現細節
1.3.1內核代碼運行級別
WindowsNT為它的內核模式的代碼分配了不同的級別。在同一個CPU上,級別低的過程可以被任何級別更大的過程中斷。級別由低到高排列如下:
級別名稱運行於該級別的過程
PASSIVE_LEVELDriverEntry,Unload,ShutDown,DispatchXxx。
APC_LEVEL在某些特殊情況下,大存儲量設備的驅動程序運行於該級別。
DISPATCH_LEVELStartIo,AdapterControl,ControllerControl,IoTimer,Dpc。
DIRQLs各種中斷處理程序。 表二
1.3.2幾個對象
i)I/O請求包(IRP)
I/O管理器每收到一個來自用戶的請求就創建一個該結構,並將其作為參數傳給驅動程序的DispatchXxx、StartIo過程。該結構中存放有請求的類型,用戶緩沖區的首地 址,用戶請求數據的長度等信息。驅動程序處理完這個請求後,也在該結構中添入處理結果的有關信息,調用IoCompleteRequest將其返回給I/O管理器,用戶程序的請求隨即 返回。
ii)DPC
當驅動程序中要用到Dpc過程時,需要創建該對象。具體作用請見1.3.3。
iii)驅動程序對象(DriverObject)
該對象在驅動程序被啟動時由I/O管理器創建,保存有該程序處理各種請求的過程入口、該程序所驅動的全部設備對象的鏈表等。
iv)設備對象(DeviceObject)