欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)邀請碼778899分享:驅(qū)動(dòng)開發(fā) nt驅(qū)動(dòng) 取消列成

柚子快報(bào)邀請碼778899分享:驅(qū)動(dòng)開發(fā) nt驅(qū)動(dòng) 取消列成

http://yzkb.51969.com/

1?。鳎椋睿洌铮鳎篁?qū)動(dòng)詳解內(nèi)容

在CancelIo的內(nèi)部會(huì)枚舉所有沒有被完成的IRP,然后依次調(diào)用IoCancelIrp。另外,如果應(yīng)用程序沒有調(diào)用CancelIo函數(shù),應(yīng)用程序在關(guān)閉設(shè)備時(shí)同樣會(huì)自動(dòng)調(diào)用CancelIo。下面的代碼演示了如何編寫取消例程。

BOOLEAN IoCancelIrp(

_In_??PIRP Irp

);

The IoCancelIrp routine sets the cancel bit in a given IRP and calls the cancel routine for the IRP if there is one

列子:

VOID

#002 CancelReadIRP(

#003 IN PDEVICE_OBJECT DeviceObject,

#004 IN PIRP Irp

#005 )

#006 {

#007 KdPrint(("Enter CancelReadIRP\n"));

#008 PDEVICE_EXTENSION pDevExt =(PDEVICE_EXTENSION)

#009 DeviceObject->DeviceExtension;

#010 //設(shè)置完成狀態(tài)為STATUS_CANCELLED

#011 Irp->IoStatus.Status =STATUS_CANCELLED;

#012 //設(shè)置IRP操作字節(jié)數(shù)

#013 Irp->IoStatus.Information =0;

#014 //結(jié)束IRP請求

#015 IoCompleteRequest( Irp, IO_NO_INCREMENT );

#016 //釋放Cancel自旋鎖

#017 IoReleaseCancelSpinLock(Irp->CancelIrql);

#018 KdPrint(("Leave CancelReadIRP\n"));

#019 }

#020

#pragma LOCKEDCODE

VOID

HelloDDKStartIO(

IN PDEVICE_OBJECT DeviceObject,

IN PIRP Irp

)

{

KIRQL oldirql;

DbgPrint("************entry HelloDDKStartIO Irp : %x\n", Irp);

//獲取cancel自旋鎖

IoAcquireCancelSpinLock(&oldirql);

if (Irp!=DeviceObject->CurrentIrp||Irp->Cancel)

{

//如果當(dāng)前有正在處理的IRP,則簡單的入隊(duì)列,并直接返回

//入隊(duì)列的工作由系統(tǒng)完成,在StartIO中不用負(fù)責(zé)

IoReleaseCancelSpinLock(oldirql);

DbgPrint("************Leave HelloDDKStartIO Irp : %x %x %d \n", Irp,DeviceObject->CurrentIrp,Irp->Cancel);

return;

}else

{

//由于正在處理該IRP,所以不允許調(diào)用取消例程

//因此將此IRP的取消例程設(shè)置為NULL

IoSetCancelRoutine(Irp,NULL);

IoReleaseCancelSpinLock(oldirql);

}

KEVENT event;

KeInitializeEvent(&event,NotificationEvent,FALSE);

//等3秒

LARGE_INTEGER timeout;

timeout.QuadPart = -3*1000*1000*10;

//定義一個(gè)3秒的延時(shí),主要是為了模擬該IRP操作需要大概3秒左右時(shí)間

KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,&timeout);

Irp->IoStatus.Status = STATUS_SUCCESS;

Irp->IoStatus.Information = 0; // no bytes xfered

IoCompleteRequest(Irp,IO_NO_INCREMENT);

DbgPrint("IoCompleteRequest HelloDDKStartIO Irp : %p\n", Irp);

//在隊(duì)列中讀取一個(gè)IRP,并進(jìn)行StartIo

IoStartNextPacket(DeviceObject,TRUE);

DbgPrint("************Leave HelloDDKStartIO Irp : %p\n", Irp);

}

#021 NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,

#022 IN PIRP pIrp)

#023 {

#024 KdPrint(("Enter HelloDDKRead\n"));

#025 //獲得的設(shè)備擴(kuò)展

#026 PDEVICE_EXTENSION pDevExt =(PDEVICE_EXTENSION)

#027 pDevObj->DeviceExtension;

#028 //設(shè)置完成例程

#029 IoSetCancelRoutine(pIrp,CancelReadIRP);

#030 //將IRP設(shè)置為掛起

#031 //掛起IRP

#032 IoMarkIrpPending(pIrp);

#033 KdPrint(("Leave HelloDDKRead\n"));

   //返回pending狀態(tài)

#035 return STATUS_PENDING;

#036 }

應(yīng)用程序

#include

#include

#include

typedef struct

{

HANDLE Device;

char index;

}pare;

UINT WINAPI Thread(LPVOID context)

{

pare *pareex=(pare *)context;

printf("Enter Thread %d\n",pareex->index);

//等待5秒

OVERLAPPED overlap={0};

overlap.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);

UCHAR buffer[10];

ULONG ulRead;

BOOL bRead = ReadFile(pareex->Device,buffer,10,&ulRead,&overlap);

//可以試驗(yàn)取消例程

CancelIo(pareex->Device);

WaitForSingleObject(overlap.hEvent,INFINITE);

printf("leave Thread %d\n",pareex->index);

return 0;

}

int main()

{

int i=0;

pare pareex[10]={0};

HANDLE hDevice =

CreateFile("\\\\.\\HelloDDK",

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//此處設(shè)置FILE_FLAG_OVERLAPPED

NULL );

if (hDevice == INVALID_HANDLE_VALUE)

{

printf("Open Device failed!");

return 1;

}

HANDLE hThread[10];

for(i=0;i<10;i++)

{

pareex[i].index=i;

pareex[i].Device=hDevice;

hThread[i] = (HANDLE) _beginthreadex (NULL,0,Thread,&pareex[i],0,NULL);

}

// hThread[1] = (HANDLE) _beginthreadex (NULL,0,Thread,&hDevice,0,NULL);

//主線程等待兩個(gè)子線程結(jié)束

WaitForMultipleObjects(i,hThread,TRUE,INFINITE);

//創(chuàng)建IRP_MJ_CLEANUP IRP

CloseHandle(hDevice);

printf("process end %d\n",i);

return 0;

}

打印信息

Enter DriverUnload Enter DriverEntry Leave DriverEntry Enter HelloDDKDispatchRoutin ?IRP_MJ_CREATE Leave HelloDDKDispatchRoutin Enter HelloDDKRead ?8ad0cf68 ************entry HelloDDKStartIO Irp : 8ad0cf68 Enter HelloDDKRead ?8b030f68 Leave HelloDDKRead ?8b030f68? ************entry OnCancelIRP Irp : 8b030f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8b030f68 ************leave OnCancelIRP Irp : 8b030f68 Enter HelloDDKRead ?8b23af68 Leave HelloDDKRead ?8b23af68? ************entry OnCancelIRP Irp : 8b23af68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8b23af68 ************leave OnCancelIRP Irp : 8b23af68 Enter HelloDDKRead ?8b130f68 Leave HelloDDKRead ?8b130f68? ************entry OnCancelIRP Irp : 8b130f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8b130f68 ************leave OnCancelIRP Irp : 8b130f68 Enter HelloDDKRead ?8a672f68 Leave HelloDDKRead ?8a672f68? ************entry OnCancelIRP Irp : 8a672f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8a672f68 ************leave OnCancelIRP Irp : 8a672f68 Enter HelloDDKRead ?8aed4f68 Leave HelloDDKRead ?8aed4f68? ************entry OnCancelIRP Irp : 8aed4f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8aed4f68 ************leave OnCancelIRP Irp : 8aed4f68 Enter HelloDDKRead ?8ad66f68 Leave HelloDDKRead ?8ad66f68? ************entry OnCancelIRP Irp : 8ad66f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8ad66f68 ************leave OnCancelIRP Irp : 8ad66f68 Enter HelloDDKRead ?8af6ef68 Leave HelloDDKRead ?8af6ef68? ************entry OnCancelIRP Irp : 8af6ef68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8af6ef68 ************leave OnCancelIRP Irp : 8af6ef68 Enter HelloDDKRead ?8adf6f68 Leave HelloDDKRead ?8adf6f68? ************entry OnCancelIRP Irp : 8adf6f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8adf6f68 ************leave OnCancelIRP Irp : 8adf6f68 Enter HelloDDKRead ?8adc6f68 Leave HelloDDKRead ?8adc6f68? ************entry OnCancelIRP Irp : 8adc6f68 ************ KeRemoveEntryDeviceQueue ?OnCancelIRP: 8adc6f68 ************leave OnCancelIRP Irp : 8adc6f68 IoCompleteRequest HelloDDKStartIO Irp : 8AD0CF68 ************Leave HelloDDKStartIO Irp : 8AD0CF68 Leave HelloDDKRead ?8ad0cf68? Enter HelloDDKDispatchRoutin ?IRP_MJ_CLEANUP Leave HelloDDKDispatchRoutin Enter HelloDDKDispatchRoutin ?IRP_MJ_CLOSE Leave HelloDDKDispatchRoutin ?

應(yīng)用打印

C:\Documents and Settings\ygc>D:\chapte Enter Thread 0 Enter Thread 1 Enter Thread 2 Enter Thread 3 Enter Thread 4 Enter Thread 5 Enter Thread 6 Enter Thread 7 Enter Thread 8 Enter Thread 9 leave Thread 4 leave Thread 1 leave Thread 6 leave Thread 8 leave Thread 3 leave Thread 7 leave Thread 2 leave Thread 9 leave Thread 5 leave Thread 0 process end ?10

C:\Documents and Settings\ygc>

IoCancelIrp在內(nèi)部會(huì)首先獲得該自旋鎖,IoCancelIrp會(huì)調(diào)用取消回調(diào)例程,因此,釋放該自旋鎖的任務(wù)就留給了取消回調(diào)例程。獲得取消自旋的函數(shù)是IoAcquire CancelSpinLock函數(shù),而釋放取消自旋鎖的函數(shù)是IoReleaseCancelSpinLock函數(shù) ?

在設(shè)置取消例程中要注意同步問題是,當(dāng)退出取消例程時(shí),一定要釋放cancel自旋鎖,否則會(huì)導(dǎo)致系統(tǒng)崩潰。另外,cancel自旋鎖是全局自旋鎖,所有驅(qū)動(dòng)程序都會(huì)使用這個(gè)自旋鎖,因此,占用自旋鎖時(shí)間不宜過長

2 在IoStartPacket內(nèi)設(shè)置取消函數(shù)

取消函數(shù)調(diào)用流程圖

下面的代碼KeLowerIrql,為什么會(huì)調(diào)

IoReleaseCancelSpinLock(pIrp->CancelIrql);//因?yàn)獒尫牛瑢?dǎo)致取消列成函數(shù)不運(yùn)行在DISPATCH_LEVEL,調(diào)用IoStartPacket函數(shù)后必須要降低運(yùn)行IRQ(pass_level)

A driver must hold the system cancel spin lock when calling this routine if the driver uses the I/O manager-supplied device queue in the device object. The driver runs at IRQL = DISPATCH_LEVEL after calling?IoAcquireCancelSpinLock?until it releases the cancel spin lock with?IoReleaseCancelSpinLock.

? KeLowerIrql(oldirql);//其實(shí)他要降低IRQL的級別是因?yàn)樵贗oStartPacket函數(shù)中如果設(shè)備是空閑的話呢會(huì)將IRQL的級別調(diào)節(jié)成DISPATCH_LEVEL

OID OnCancelIRP(PDEVICE_OBJECT DeviceObject, PIRP pIrp){

2

3 UINT32* InputBuffer = (UINT32*)pIrp->AssociatedIrp.SystemBuffer;

4 DbgPrint("Enter OnCancelIRP:%d!\n", *InputBuffer);

5 if (pIrp == DeviceObject->CurrentIrp){

6 //此IRP不在隊(duì)列中,正在由StartIO處理

7 DbgPrint("Current IRP OnCancelIRP!\n");

8 KIRQL oldirql = pIrp->CancelIrql;//保存原先的IRQL

9 IoReleaseCancelSpinLock(pIrp->CancelIrql);

10 IoStartNextPacket(DeviceObject, TRUE);

11 KeLowerIrql(oldirql);//其實(shí)他要降低IRQL的級別是因?yàn)樵贗oStartPacket函數(shù)中如果設(shè)備是空閑的話呢會(huì)將IRQL的級別調(diào)節(jié)成DISPATCH_LEVEL

12 }

13 else{//當(dāng)irp != fdo->CurrentIrp的時(shí)候,這個(gè)很好理解,

14 //就是需求取消的irp還沒有被執(zhí)行,那么也就是說還在隊(duì)列里面,直接把這個(gè)irp從隊(duì)列里面刪除就可以了。

15 DbgPrint("Uncurrent IRP OnCancelIRP!\n");

16 KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,

17 &pIrp->Tail.Overlay.DeviceQueueEntry);

18 IoReleaseCancelSpinLock(pIrp->CancelIrql);

19 }

20 pIrp->IoStatus.Status = STATUS_CANCELLED;

21 pIrp->IoStatus.Information = 0;

22 IoCompleteRequest(pIrp, IO_NO_INCREMENT);

23 DbgPrint("Leave OnCancelIRP:%d!\n", *InputBuffer);

24 }

首先因?yàn)镮/O管理器在調(diào)用取消例程前會(huì)先調(diào)用IoAcquireCancelSpinLock來獲取自旋鎖,那么在取消例程里面切記一定要調(diào)用IoReleaseCancelSpinLock來釋放自旋鎖。

取消例程里面有個(gè)判斷語句if (Irp == DeviceObject->CurrentIrp),

1. 當(dāng)irp != fdo->CurrentIrp的時(shí)候,這個(gè)很好理解,就是需求取消的irp還沒有被執(zhí)行,那么也就是說還在隊(duì)列里面,直接把這個(gè)irp從隊(duì)列里面刪除就可以了。

2. 當(dāng)irp == fdo->CurrentIrp的時(shí)候,這是個(gè)有趣的時(shí)間點(diǎn),這個(gè)時(shí)間點(diǎn)處于fdo->CurrentIrp=Irp(IoStartPacket或者IoStartNextPacket)和IoAcquireCancelSpinLock(StartIo例程)之間。因?yàn)樾枰∠膇rp已經(jīng)不在隊(duì)列中了,那么就無需操作隊(duì)列。在取消例程里面只要調(diào)用IoStartNextPacket就可以了(也就是跳過了當(dāng)前irp的處理)https://blog.csdn.net/zj510/article/details/8287712

鏈接位置:《Windows驅(qū)動(dòng)開發(fā)技術(shù)詳解》之StartIO例程 - _No.47 - 博客園 (cnblogs.com)

柚子快報(bào)邀請碼778899分享:驅(qū)動(dòng)開發(fā) nt驅(qū)動(dòng) 取消列成

http://yzkb.51969.com/

參考鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/18881794.html

發(fā)布評論

您暫未設(shè)置收款碼

請?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄