驅動程式 - Kernel Mode Driver Framework (KMDF) - 教學說明 - 5. File Buffer的使用策略



在AddDevice()中,會初始化相關旗標,其中有一個設定是關於I/O Manager的Buffer使用方式

NTSTATUS AddDevice(WDFDRIVER myDriver, PWDFDEVICE_INIT pMyDeviceInit)
{
    ...
    WdfDeviceInitSetIoType(pMyDeviceInit, WdfDeviceIoBuffered);
    ...
}

該參數主要用於什麼地方呢?

當User Application透過檔案系統跟驅動程式溝通時,User Application會將Buffer Pointer傳給Win32 API

int __cdecl main(int argc, char **argv)
{
    ...
    ReadFile(hFile, szBuffer, sizeof(szBuffer), &dwRet, NULL);
    WriteFile(hFile, szBuffer, sizeof(szBuffer), &dwRet, NULL);
    ...
}

P.S. szBuffer是User Buffer Pointer

當User Application呼叫ReadFile()、WriteFile()後,I/O Manager會呼叫驅動程式的EvtIoRead、EvtIoWrite Callback副程式,那在驅動程式的Callback副程式要如何拿到User Application的Buffer資料呢?User Space的資料位址跟Kernel Space的資料位址是位於不同的地址空間,意思就是驅動程式不能直接存取這個User Buffer Pointer,所以I/O Manager要如何將這塊Buffer交給驅動程式,其使用的方式,就是所謂I/O Manager的Buffer使用策略,在Windows驅動程式中,I/O Manager有三種Buffer使用方式

使用方式行為描述
WdfDeviceIoBufferedI/O Manager會新增一塊跟User Buffer一樣大小的記憶體,讀寫都需要由I/O Manager負責同步更新(進行複製的動作)
WdfDeviceIoDirectI/O Manager會Mapping User Buffer到一個MDL(Memory Description List),驅動程式使用這個MDL進行操作,相較於WdfDeviceIoBuffered,因為資料不須由I/O Manager做複製的動作,因此,效率會比較好
WdfDeviceIoNeitherNeither I/O的意思是Neither Buffered Nor Direct I/O,使用這種方式時,I/O Manager會將Use Buffer Pointer,透過特殊操作後,再傳遞給驅動程式使用,因為,驅動程式可以直接存取User Buffer的資料,因此,效率是這三種方式裡面最好的一個

驅動程式必須依據Buffer的設定去存取不同欄位的Pointer,這樣才可以正確存取到User Buffer

使用方式CallbackBuffer PointerBuffer Length
WdfDeviceIoBufferedEvtIoRead()WdfRequestRetrieveOutputMemory()第三個參數(Length)
EvtIoWrite()WdfRequestRetrieveInputMemory()第三個參數(Length)
WdfDeviceIoDirect(PIO)EvtIoRead()WdfRequestRetrieveOutputWdmMdl()第三個參數(Length)
EvtIoWrite()WdfRequestRetrieveInputWdmMdl()第三個參數(Length)
WdfDeviceIoDirect(DMA)EvtIoRead()WdfRequestRetrieveOutputWdmMdl()第三個參數(Length)
EvtIoWrite()WdfRequestRetrieveInputWdmMdl()第三個參數(Length)
WdfDeviceIoNeitherEvtIoRead()WdfRequestRetrieveUnsafeUserOutputBuffer()第三個參數(Length)
EvtIoWrite()WdfRequestRetrieveUnsafeUserInputBuffer()第三個參數(Length)