玩玩DriverWorks(三)-串行化IO請求
周末實(shí)在不太想寫我的數(shù)據(jù)庫程序,,又花了一個(gè)小時(shí)練習(xí)了一下DriverWorks里的排隊(duì)IO請求模型,,其實(shí)這和DDK中的模型基本上是一樣的,,因?yàn)閰⒖剂薖rogramming the Microsoft Windows Driver Model里的一些代碼,,并且少看了DriverWorks關(guān)于排隊(duì)IO的一句話,,我還得到了一個(gè)BSOD,,不過這個(gè)BSOD讓我注意到了幫助文檔上我沒有注意到的地方,,呵呵! 廢話不多說,,來一個(gè)段代碼! #define VDW_MAIN #include "vdw.h" //Begin Device Code/////////////////////////////////////////////////////// NTSTATUS SerialRead(KIrp I); CQueueDevice::CQueueDevice():KDevice(L"CQueueDevice",FILE_DEVICE_UNKNOWN,L"CQueueDevice",0,DO_DIRECT_IO) NTSTATUS CQueueDevice::ComplateIrp(KIrp I) return STATUS_SUCCESS; NTSTATUS CQueueDevice::CleanUp(KIrp I) return ComplateIrp(I); NTSTATUS CQueueDevice::Close(KIrp I) return ComplateIrp(I); NTSTATUS CQueueDevice::DeviceControl(KIrp I) //排隊(duì)并設(shè)置取消例程 NTSTATUS CQueueDevice::Read(KIrp I) //排隊(duì)并設(shè)置取消例程 NTSTATUS CQueueDevice::Write(KIrp I) //排隊(duì)并設(shè)置取消例程 NTSTATUS CQueueDevice::SerialRead(KIrp I) KMemory mem(I.Mdl()); PVOID pOutputBuf=mem.MapToSystemSpace(); //從設(shè)備讀數(shù)據(jù)輸出到pOutputBuf里 //返回處理狀態(tài) NTSTATUS CQueueDevice::SerialWrite(KIrp I) KMemory mem(I.Mdl()); PVOID pInputBuf=mem.MapToSystemSpace(); //將pInputBuf里的數(shù)據(jù)輸出到設(shè)備 //返回處理狀態(tài) NTSTATUS CQueueDevice::SerialIoControl(KIrp I) I.Information()=0; VOID CQueueDevice::CancelIo(KIrp I) VOID CQueueDevice::StartIo(KIrp I) if (I.WasCanceled()) NTSTATUS status=STATUS_SUCCESS; switch(I.MajorFunction()) { NextIrp(I); /* 文檔上有這樣一段: When processing of the IRP is complete, the driver calls NextIrp. This function does two things: it tells the I/O Manager to pass the next IRP in the device's IRP queue to StartIo, and it tells the I/O Manager that processing of the current IRP is complete. 說了NextIrp做兩件事情,我沒有看仔細(xì)結(jié)果藍(lán)屏了,看一下KDevice::NextIrp的實(shí)現(xiàn)代碼就知道為什么了: //End of Device Code////////////////////////////////////////////////////// //Begin Driver Code////////////////////////////////////////////////////////// DECLARE_DRIVER_CLASS(CQueueDriver,NULL) NTSTATUS CQueueDriver::DriverEntry(IN PUNICODE_STRING RegistryPath) CQueueDevice *pDevice=new(NonPagedPool)CQueueDevice(); return status; VOID CQueueDriver::Unload() 其實(shí)這只是一個(gè)簡化的IO請求模型演示,因?yàn)槲覜]有什么具體的PCI設(shè)備可供我寫驅(qū)動用,正如Programming the Microsoft Windows Driver Model一書中的一張圖表示的那樣: 一個(gè)讀寫請求,首先到達(dá)IO管理器,然后到達(dá)派遣例程(Read,Write,DeviceControl它們排隊(duì)IRP請求),再到達(dá)StartIo中處理IRP,如果必要的話,StartIo會發(fā)出in,out之類的命令給硬件設(shè)備,可能立即返回也可能設(shè)備完成操作后發(fā)出一個(gè)中斷,然后驅(qū)動的中斷服務(wù)例程ISR被執(zhí)行,ISR調(diào)度DPC來管理這個(gè)中斷,DPC拿到數(shù)據(jù)后完成這個(gè)請求,因?yàn)镈PC例程是在DISPATCH_LEVEL級上運(yùn)行的,它比ISR受到的限制少,它處理完數(shù)據(jù)后可以調(diào)用IoCompleteRequest或是IoStartNextPacket這樣的例程,最后IRP回到IO管理器,返回上層.在DriverWorks的例子驅(qū)動BasicPci中可以非常清楚的看到這樣的代碼流程. 這些概念在看Programming the Microsoft Windows Driver Model一書時(shí)使終弄的不是很清楚,,但用DriverWorks寫驅(qū)動后,感覺自己對驅(qū)動程序的整體結(jié)構(gòu)有了更深入的了解.看來我還是適合看一些面向?qū)ο蟮拇a,再由這些代碼底層實(shí)現(xiàn)到學(xué)習(xí)如何在非面向?qū)ο鬆顟B(tài)時(shí)怎么實(shí)現(xiàn)這些東西.也許這就是從做應(yīng)用開發(fā)轉(zhuǎn)到驅(qū)動開發(fā)的人和直接從事驅(qū)動開發(fā)的人,接受東西的角度不同吧!Driverworks在用純DDK寫驅(qū)動的人看來是很煩瑣的,但在我看來代碼結(jié)構(gòu)卻是那么簡潔合理.在這個(gè)例子里實(shí)現(xiàn)這些機(jī)制,代碼里還有注釋但卻不到250行,而且代碼非常容易理解,呵呵! |
|