當 i/o 管理器載入乙個裝置驅動程式時,它會建立乙個驅動程式物件,該物件在物件管理器目錄中的路徑為:\driver\或\filesystem\。如果是檔案系統型別的驅動程式,則該物件被放置在 "\filesystem"目錄下,否則放在"\driver"目錄下。因此,驅動程式可粗略地分為檔案系統驅動程式和非檔案系統驅動程式。
與驅動程式相關的另一種物件是裝置物件。每個裝置物件代表了系統中的乙個裝置,包括邏輯裝置和物理裝置。正常情況下,有兩種途徑可建立裝置物件:即插即用管理器在檢測到裝置時,通過呼叫驅動程式的adddevice 例程來建立裝置物件;或者,非即插即用驅動程式在它們的初始化例程中建立裝置物件。每個裝置物件都必定有乙個為它負責的驅動程式。對裝置物件的各種操作實際上是由為它負責的驅動程式中的例程來完成的。乙個驅動程式可以支援多個裝置,所以,驅動程式物件中有乙個鍊錶記錄了它所負責的所有裝置物件。
在windows中,裝置物件的建立是通過 i/o 管理器的iocreatedevice函式來完成的,函式原型如下:
driverobject 引數指向負責該裝置的驅動物件;deviceextensionsize 引數定義了待建立裝置物件的擴充套件部分大小,此擴充套件部分是由驅動程式來指定和使用的;devicename 可選引數指定了裝置的名稱。devicetype 引數定義了裝置的型別,device_type 是無符號整數型別, microsoft 已經預定義了所有常用的裝置,它們的整數值小於 32767, 若建立者需要使用自定義的裝置型別,可以使用大於 32767 的值。關於這些預定義值,參見 public\sdk\inc\devioctl.h 檔案中的常量定義。devicecharacteristics引數指定了裝置的特徵; exclusive 引數指定了在建立裝置物件時是否使用互斥標誌;deviceobject 引數是乙個輸出引數,用於存放所建立的裝置物件。
iocreatedevice函式,首先根據引數中指定的要求,構造出裝置的名稱,並且建立乙個安全描述符,用於對該裝置的訪問控制。然後,呼叫obcreateobject 函式建立乙個 iodeviceobjecttype 型別的核心物件。如果由於自動產生的名稱發生衝突而導致obcreateobject 呼叫不成功,則重試此過程。然後,iocreatedevice 函式初始化所建的裝置物件中的成員,並呼叫obinsertobject 函式,將裝置物件插入到程序的控制代碼表中。最後,設定該裝置物件中的驅動程式物件,並將裝置物件插入到驅動程式物件的裝置鍊錶中,因而將裝置物件與驅動程式物件關聯起來。
下面看一下驅動程式物件和裝置物件的定義。以下是驅動程式物件的資料結構:
typedef struct _driver_object driver_object;
//以下是擴充套件部分的資料結構 driver_extension的定義
typedef struct _driver_extension driver_extension, *pdriver_extension;
驅動程式物件中的 majorfunction 陣列包含了一組例程,當 i/o 管理器接收到乙個 i/o 請求時,它將根據 i/o 請求中的有關資訊,找到裝置物件的驅動程式物件,並呼叫驅動程式中相應的例程來處理該 i/o 請求。通常, 裝置驅動程式的初始化例程會填充majorfunction 陣列中的例程。對於初始化例程未填充的陣列項,建立驅動程式物件的函式(如ioploaddriver 和 iocreatedriver)會將其填充為 iopinvaliddevicerequest 函式。
下面是裝置物件的資料結構:
typedef struct _device_object queue;
ulong alignmentrequirement; //緩衝區的對齊要求, 其值等於對其邊界減一
kdevice_queue devicequeue; //裝置佇列,存放針對該裝置的 i/o 請求
kdpc dpc;
ulong activethreadcount; // 使用者檔案系統:使用此裝置物件的執行緒數
psecurity_descriptor securitydescriptor; //裝置的安全描述符
kevent devicelock; //裝置鎖
ushort sectorsize; //扇區大小
ushort sparel;
struct _devobj_extension *deviceobjectextension; // 指向擴充套件部分
ushort reserved;
} device_object;
typedef struct _device_object *pdevice_object;
裝置物件擴充套件部分的定義如下:
typedef struct _devobj_extension device_extension, *pdevobj_extension;
裝置物件描述了乙個特定裝置的狀態資訊,包括它所接收到的 i/o 請求和裝置的電源特性等。正如我們在 iocreatedevice 函式中看到的那樣, 裝置物件的 driverobject 域指向負責該裝置的驅動程式,而它的 nextdevice 域構成了同屬乙個驅動程式的裝置物件單鏈表。iocreatedevice 呼叫 iopinsertremovedevice 函式,將裝置物件插入到此鍊錶中。另一方面,裝置物件的 attacheddevice 域和擴充套件部分的 attachedto 域構成了乙個雙鏈表節點中的前後指標。在windows 的層次驅動程式模型中,i/o請求可以被傳遞給乙個裝置棧進行處理。裝置棧中的裝置物件相互鏈結起來,建立這些裝置物件的驅動程式相互協作來處理針對特定裝置的 i/o 請求。因而, 當 i/o 管理器接收到針對這一裝置的 i/o 請求時, 它會一次將該 i/o 請求傳遞給這些裝置物件,交給它們處理。裝置物件的stacksize 域制定了為處理 i/o 請求而最小需要的棧深度,而 attachedto 成員將裝置展中的裝置物件子棧頂向底層(接近硬體裝置的裝置物件)鏈結起來,attacheddevice 成員則相反地自底向上將這些裝置物件鏈結起來。
圖6.5顯示了在虛擬機器環境中 windows server 2003 sp1系統的三個裝置物件所構成的裝置棧,我們可以看到裝置物件中的 attacheddevice 和 attachedto 成員所形成的鍊錶結構。驅動程式 acpi 建立了最底層的裝置物件 「\device\0000003b」 ,它要求最小的棧深度為4,這是在 acpi驅動程式中指定的。驅動程式 i8042prt 建立了中間的無名裝置物件,它的 adddevice 例程呼叫 ioattachdevicetodevicestack 函式,完成此無名裝置物件的掛載工作。進一步,驅動程式kbdclass建立了最上面的裝置物件 "\device\keyboardclass0" , 類似地,它的 adddevice 例程呼叫 ioattachdevice 函式,完成 keyboardclass0 裝置物件的掛載工作。
Windows核心原理與實現之核心載入
在intel x86系統上,windows作業系統獲得控制首先從硬碟的主引導記錄 mbr 開始,windows setup程式在安裝windows時填充mbr 其他的磁碟管理器也可能填充mbr mbr包含 和資料,其 稱為引導 在系統引導時首先獲得控制 mbr中的資料時一張分割槽表,制定了每個分割槽...
windows核心原理與實現
本文章是作者本人在學習 windows原理與實現 一書時的一些總結和筆記 2.1處理器模式 intelx86處理器 0 最高端特權,cpu處在核心模式,可以訪問當前程序的位址空間和系統空間 3 最低特權,處在使用者模式,只能訪問當前程序的位址空間。2.2記憶體管理 共享的系統位址空間和私有的程序位址...
Windows核心原理與實現讀書筆記之異常分發
異常分發 在intel x86 體系結構中,異常也是通過idi 中斷描述符表 分發的。異常記錄exception record 定義 typedef struct exception record exception record,pexception record 異常處理例程 kitapxx 如...