驅動雜記2 分層驅動,IRP ,I O堆疊初步印象

2021-06-05 20:07:28 字數 2927 閱讀 5671

分層驅動是指兩個或者兩個以上的驅動程式,他們分別建立裝置物件,並且形成乙個由高到低的

裝置物件棧。irp請求一般會被傳送到裝置棧的最頂層裝置物件,頂層裝置物件可以選擇直接結束irp

請求,也可以選擇將irp請求向下層裝置**。如果是向下層裝置**,當irp請求結束時,irp會順著

裝置棧的反方向原路返回。當得知下層驅動程式已經結束irp請求時,本層裝置物件可以選擇繼續向上

返回,也可以重新選擇將irp再次傳遞給底層裝置驅動。

兩層裝置之間通常用irp傳遞請求。irp由i/o管理器建立發出,i/o管理器是使用者態與核心態之間的橋梁,

i/o管理器捕獲使用者態請求,將其轉換為irp請求,傳送給驅動程式。

以createfile為例來理解(僅供參考),假設要開啟乙個檔案"c:\filiename"這個名字在使用者態下有意義,

它有乙個symbol link(符號鏈結)"\??\filiename」,在核心模式下它的真實名字為"\device\harddiskvolume1\filiename"

使用者態函式只能通過符號鏈結來開啟某個裝置,i/o管理器捕獲到這個請求,呼叫物件管理器(object manager)

同時呼叫安全引用監視器檢查該子系統是否有開啟裝置物件的許可權。獲取符號鏈結後,呼叫zwcreatefile

完成開啟裝置的工作,並且得到乙個檔案控制代碼。zwcreatefile通過系統服務呼叫核心函式ntcreatefile.在

ntcreatefile執行過程中,執行到nt!ioporsedevice中呼叫t!iogetattacheddevice,通過pdo獲得鍵盤裝置棧最頂端的

裝置物件,用得到的這個裝置物件的stacksize(io_stack_location的大小)成員作為引數來呼叫函式

ioallocateirp建立irp,呼叫nt!obcreateobject建立檔案物件,並初始化這個檔案物件。呼叫nt!iocalldriver將irp發往驅動。

驅動處理完這個 irp 之後,返回 nt!iopparsedevice 繼續執行。

初步了解了irp的建立,我們來看一下這個irp的結構。irp包括兩個部分,首部和輔助。首部包括指向irp輸入輸出

緩衝區的指標,當前擁有irp驅動的指標,io_stack_location的陣列索引,同時也有乙個指向該io_stack_location

的指標。索引是從1開始,沒有0。緊接首部的是乙個io_stack_location(i/o堆疊單元)陣列,它的大小由裝置棧中

裝置數決定。io_stack_location的每個元素和每個裝置一一對應。

irp的結構的大小是不固定的,大體結構如下:

--------------------

| irp header |

--------------------

|io_stack_location |<-----lowest driver stack location #index1

--------------------

|io_stack_location |<-----next higher stack location #index2

--------------------

......

|io_stack_location |<-----topmost driver stack location #indexn        //類似棧,遵循先進後出

裝置物件收到irp請求通過driverobject成員找到驅動程式,驅動程式訪問它對應的裝置物件在io_stack_location

陣列中元素檢查引數,以決定如何操作(如majorfunction對應的派遣函式)

typedef struct _io_stack_location io_stack_location

我們再來看irp在分層驅動中的傳遞。當驅動程式準備向次低層驅動程式傳遞irp時可以呼叫iocalldriver例程,

它其中的乙個工作是遞減當前io_stack_location的索引,使之與下一層的驅動程式匹配。但該索引不會設定成0

,如果設定成0,系統將會崩潰。就是說,最底層的驅動程式不會呼叫iocalldriver例程。

假設有乙個請求,i/o管理器為這個請求建立了irp並分配了4個io_stack_location 單元。

nt i/o管理器將irp頭中的stackcount欄位初始化為irp中stack location的總數。irp頭中的

currentlocation欄位初始化為stackcount+1(即在這個分配了4個io_stack_location

單元的irp中currentlocation被初始化為4+1=5),每一次通過iocalldriver()呼叫驅動的派遣函式時,這個值減1。

當i/o管理器在呼叫驅動時,它總是將irp的stacklocation指標指向下乙個stacklocation;當被呼叫的驅動釋放irp時,

stack location真正被指回到前乙個stack location。因此當過濾驅動的派遣函式執行時,i/o管理器使用stack location #4,

也就是分配的最後乙個stack location。

好了,我們來看傳遞步驟

1.為下乙個io_stack_location結構設定引數 可以通過iogetnextirpstacklocation獲得下個結構的指標

如果需要設定完成例程,呼叫iocopycurrentirpstacklocationtonext巨集

如果不設定完成例程,呼叫ioskipcurrentirpstacklocation  巨集(currentlocation+1)過濾驅動常用

2.根據需要設定完成例程

3呼叫iocalldriver函式將irp請求傳遞給下一層驅動。此時當前驅動不再擁有該irp的訪問權,如果還需要訪問必須設定

完成例程。

通過以上整理,對分層驅動,irp的運轉機制,i/o堆疊有乙個初步的概念上的了解,當然實際運用中會涉及到一些細節上

的問題,在以後繼續的使用當中來完善這些知識點。

解構領域驅動設計(二) 分層架構

反映業務規則的 是整個軟體的核心,但是它一般只佔很小的一部分,在傳統的基於貧血模型的分層軟體架構中,業務規則可能分散到各個層 各個 段,從而使得通過 來還原業務規則或者保證 與業務規則一致將變得非常困難。ddd分層架構的核心思想就是將所有業務規則的 抽取到領域層,保證領域層的編碼與領域模型是完全一致...

解構領域驅動設計(二) 分層架構

反映業務規則的 是整個軟體的核心,但是它一般只佔很小的一部分,在傳統的基於貧血模型的分層軟體架構中,業務規則可能分散到各個層 各個 段,從而使得通過 來還原業務規則或者保證 與業務規則一致將變得非常困難。ddd分層架構的核心思想就是將所有業務規則的 抽取到領域層,保證領域層的編碼與領域模型是完全一致...

2,分層的思想

在分解複雜的軟體系統時,軟體設計者使用最多的技術之一就是分層,在計算機本身的架構中也可以看到。存cpu指令集和裝置驅動程式,在到內部晶元和各個邏輯閘電路。網路中,ftp層架構在tcp之上,tcp架構 在ip之上,ip架構又在乙太網之上。在這種組織方式下 上層使用了下層定義的各種服務,而下層對上層一無...