久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

玩玩DriverWorks(三)

 李林俠圖書館 2011-12-12

玩玩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
#define DRIVER_FUNCTION_UNLOAD
#define DRIVER_FUNCTION_CREATE
#define DRIVER_FUNCTION_CLEANUP
#define DRIVER_FUNCTION_CLOSE
#define DRIVER_FUNCTION_READ
#define DRIVER_FUNCTION_WRITE
#define DRIVER_FUNCTION_STARTIO
#define DRIVER_FUNCTION_DEVICE_CONTROL

#include "vdw.h"

//Begin Device Code///////////////////////////////////////////////////////
class CQueueDevice:public KDevice
{
 SAFE_DESTRUCTORS;
public:
 CQueueDevice();
 NTSTATUS ComplateIrp(KIrp I);
 DEVMEMBER_DISPATCHERS;
 DEVMEMBER_CANCELIRP(CQueueDevice,CancelIo);

 NTSTATUS SerialRead(KIrp I);
 NTSTATUS SerialWrite(KIrp I);
 NTSTATUS SerialIoControl(KIrp I);
};

CQueueDevice::CQueueDevice():KDevice(L"CQueueDevice",FILE_DEVICE_UNKNOWN,L"CQueueDevice",0,DO_DIRECT_IO)
{
 if(!NT_SUCCESS(ConstructorStatus()))
 {
  DbgPrint(__FUNCTION__":Failed to Create Device\n");
 }
}

NTSTATUS CQueueDevice::ComplateIrp(KIrp I)
{
 I.Information()=0;
 I.Complete(STATUS_SUCCESS);

 return STATUS_SUCCESS;
}
NTSTATUS CQueueDevice::Create(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");
 
 return ComplateIrp(I);
}

NTSTATUS CQueueDevice::CleanUp(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 return ComplateIrp(I);
}

NTSTATUS CQueueDevice::Close(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 return ComplateIrp(I);
}

NTSTATUS CQueueDevice::DeviceControl(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 //排隊(duì)并設(shè)置取消例程
 return QueueIrp(I,LinkTo(CancelIo));
}

NTSTATUS CQueueDevice::Read(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 //排隊(duì)并設(shè)置取消例程
 return QueueIrp(I,LinkTo(CancelIo));
}

NTSTATUS CQueueDevice::Write(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 //排隊(duì)并設(shè)置取消例程
 return QueueIrp(I,LinkTo(CancelIo));
}

NTSTATUS CQueueDevice::SerialRead(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 KMemory mem(I.Mdl());

 PVOID pOutputBuf=mem.MapToSystemSpace();
 ULONG OutputSize=I.ReadSize();

 //從設(shè)備讀數(shù)據(jù)輸出到pOutputBuf里
 //填寫輸出長度,它<=OutputSize
 ULONG nBytesReturned=0;
 I.Information()=nBytesReturned;

 //返回處理狀態(tài)
 return STATUS_SUCCESS;
}

NTSTATUS CQueueDevice::SerialWrite(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 KMemory mem(I.Mdl());

 PVOID pInputBuf=mem.MapToSystemSpace();
 ULONG InputSize=I.WriteSize();

 //將pInputBuf里的數(shù)據(jù)輸出到設(shè)備
 I.Information()=0;

 //返回處理狀態(tài)
 return STATUS_SUCCESS;
}

NTSTATUS CQueueDevice::SerialIoControl(KIrp I)
{
 DbgPrint(__FUNCTION__"\n");

 I.Information()=0;
 return STATUS_SUCCESS;
}

VOID CQueueDevice::CancelIo(KIrp I)
{
 if(CurrentIrp()==I)
 {
  //如果取消的是當(dāng)前的請求,直接返回NextIrp會完成這個(gè)請求,
  //并開始下一個(gè)請求
  CancelSpinLock::Release(I.CancelIrql());
  I.Information() = 0;
  I.Status() = STATUS_CANCELLED;
  NextIrp(I);
 }
 else
 {
  //如果是一個(gè)排隊(duì)的請求,則從設(shè)備排隊(duì)摘除,完成這個(gè)請求,
  //并返回"已取消"狀態(tài)碼
  KDeviceQueue dq(DeviceQueue());
  BOOLEAN bRemoved=dq.RemoveSpecificEntry(I);
  CancelSpinLock::Release(I.CancelIrql());
  if(bRemoved)
  {
   I.Information()=0;
   I.Complete(STATUS_CANCELLED);
  }
 }
}

VOID CQueueDevice::StartIo(KIrp I)
{
 CancelSpinLock::Acquire();

 if (I.WasCanceled())
 {
  //如果是已經(jīng)取消的
  CancelSpinLock::Release();
  return;
 }
 else
 {
  //如果沒有取消,則設(shè)空取消例程,然后處理
  I.SetCancelRoutine(NULL);
  CancelSpinLock::Release();
 }

 NTSTATUS status=STATUS_SUCCESS;

 switch(I.MajorFunction()) {
 case IRP_MJ_READ:
  status=SerialRead(I);
  break;
 case IRP_MJ_WRITE:
  status=SerialWrite(I);
  break;
 case IRP_MJ_DEVICE_CONTROL:
  status=SerialIoControl(I);
 }

 NextIrp(I);
 //不要在這里需要調(diào)用I.Complete(),因?yàn)镵Device::NextIrp里調(diào)用了一次
 
 return;
}

/*
我在上面這個(gè)return前調(diào)用了I.Complete,結(jié)果得到了一個(gè)BSOD,錯(cuò)誤代碼是"多次
完成IRP請求",發(fā)現(xiàn)我的英文水平略有長進(jìn),呵呵!在沒有金山詞霸的幫助下(BSOD了),
可以知道是什么錯(cuò)誤.

文檔上有這樣一段:
Subclasses of KDevice that use StartIo can use member function CurrentIrp to obtain a pointer to the IRP that the device is currently processing.

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)代碼就知道為什么了:
inline VOID KDevice::NextIrp(KIrp I, CCHAR PriorityBoost, BOOLEAN Cancelable)
{
 BOUNDS_CHECKER(NEXT_IRP, (this, I.m_Irp));
 IoStartNextPacket(m_pDeviceObject, Cancelable);
 if (!I.IsNull())
  {IoCompleteRequest(I.m_Irp, PriorityBoost);}
}
*/

//End of Device Code//////////////////////////////////////////////////////

//Begin Driver Code//////////////////////////////////////////////////////////
class CQueueDriver:public KDriver
{
 SAFE_DESTRUCTORS;
public:
 virtual NTSTATUS DriverEntry(IN PUNICODE_STRING RegistryPath);
 virtual VOID Unload();
};

DECLARE_DRIVER_CLASS(CQueueDriver,NULL)

NTSTATUS CQueueDriver::DriverEntry(IN PUNICODE_STRING RegistryPath)
{
 DbgPrint(__FUNCTION__"\n");
 NTSTATUS status=STATUS_SUCCESS;

 CQueueDevice *pDevice=new(NonPagedPool)CQueueDevice();
 if(pDevice)
 {
  status=pDevice->ConstructorStatus();
  if(!NT_SUCCESS(status))
  {
   delete pDevice;
  }
 }

 return status;
}

VOID CQueueDriver::Unload()
{
 DbgPrint(__FUNCTION__"\n");
 KDriver::Unload();
}
//End of Driver code//////////////////////////////////////////////////////

其實(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行,而且代碼非常容易理解,呵呵!

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多