Windows核心-7-(IRP)I/O請求包
IRP(I/O Request Packet)就是一個進行I/O操作的請求包。
IRP是一個結構體,誰分配誰就得釋放,通常由執行體裡的管理器,獲取核心驅動程式來分配。
IRP不是單獨的,只要建立了IRP就會跟著建立IRP的I/O棧,有一個棧是給核心驅動用的:
驅動需要呼叫IoGetCurrentIrpStackLocation函式來獲取內驅驅動對應的I/O棧。
I/O傳遞
I/O系統是以裝置物件為中心,而不是以驅動物件為中心的。IRP可以在裝置物件中傳來傳去:
有點類似於計算機網路的體系結構。但是不可否認的是I/O可以在裝置直接進行各種傳遞,所以通常用來作為讀取文字資料。
具體的傳遞過程有點類似於棧。
IRP和I/O棧
這張圖是對前面第一張圖的細化。
分發例程(dispatch routine)
IRP最主要的一個作用就是拿來做分發例程,其實也就是分發的例項函式,就是對檔案資料的傳遞。在我的理解裡,就是對資訊的分發,讓大家一起用到資料。
所有的分發例程都有一個原型:
typedef NTSTATUS DRIVER_DISPATCH (
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp);
分發例程必須儲存在驅動物件的MajorFunction裡面,且需要對應和驅動的連線狀態:
狀態 | 描述 |
---|---|
IRP_MJ_CREATE | 獲取檔案控制代碼,對應User下的CreateFile |
IRP_MJ_CLOSE | 關閉檔案控制代碼,對應User下的CloseHandle |
IRP_MJ_READ | 對應ReadFile |
IRP_MJ_WRITE | 對應WriteFile |
IRP_MJ_DEVICE_CONTROL | 對應DeviceIoControl,即可讀又可寫 |
IRP_MJ_INTERNAL_DEVICE_CONTROL | 和IRP_MJ_DEVICE_CONTROL差不多,但是隻有Kernel可用 |
完成請求
一旦決定要處理IRP(意味著不會把該IRP傳遞給下一個裝置物件),就必須要完成它。
比如:
NTSTATUS MyDispatchRoutine(PDEVICE_OBJECT, PIRP Irp) {
//...
Irp->IoStatus.Status = STATUS_XXX;
Irp->IoStatus.Information = NumberOfBytesTransfered; // depends on request type
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_XXX;
}
//這裡的IoCompleteRequest就是必須的
安全IRP操作
由於執行緒原因,很有可能一個去讀一個去寫,導致兩個只有一個拿到了想要的資料。
還有頁面記憶體的原因,修改的時候有可能一起修改了。
核心提供了兩種比較安全的處理方式:
1 緩衝I/O
2 直接I/O
緩衝I/O
要使用緩衝I/O只需要在裝置物件的Flag欄位裡面新增一個DO_BUFFERED_IO
DeviceObject->Flags |= DO_BUFFERED_IO
緩衝I/O的原理就是在系統記憶體中開闢一段緩衝區,作為一箇中間人。
比如說要寫,就先把內容寫到系統記憶體緩衝區裡,然後系統記憶體緩衝區再寫入/讀取到緩衝區裡面。
直接I/O
直接緩衝採用實體記憶體對映來處理,將User和Kernel的緩衝區都指向實體記憶體裡面,並且鎖定在記憶體裡,然後讀寫都採用它。這樣的好處是減少了呼叫的開銷。但是佔了部分記憶體。
IRP_MJ_DEVICE_CONTROL 排程
前面的緩衝和直接I/O是讀或寫操作,這裡的IRP_MJ_DEVICE_CONTROL操作是基於控制程式碼來選擇讀或寫兩個都可以的。
User態的IRP_MJ_DEVICE_CONTROL 和Kernel態的呼叫函式原型差不多:
BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
dwIoControlCode:控制程式碼,由CTL_CODE巨集的四個引數來處理。
Zero驅動程式
Client+Kernel的一個練手專案:
對於讀請求,會將提供的緩衝區清零然後輸出
對於寫請求,會把緩衝區消耗掉
原始碼zodiacon/windowskernelprogrammingbook: The Windows Kernel Programming book samples (github.com)