关于IRP队列的疑问?

whatday 2011-12-29 03:01:03
最近学习驱动编程遇到一些问题 还请各位高手帮忙解答一下哈 先谢谢了

问题一:DDK提供KDEVICE_QUEUE存储队列 队列中的每个元素用KDEVICE_QUEUE_ENTRY来表示 但是在KDEVICE_QUEUE中并没有见到有成员KDEVICE_QUEUE_ENTRY 是不是因为 KDEVICE_QUEUE 和 KDEVICE_QUEUE_ENTRY 是通过链表连接的呢?他们的包含关系只是一个逻辑上的链表,不是像一般的数据结构那样包含的吧?

问题二:在应用程序里,两个并行的线程A,B 线程执行函数代码一样 向设备发出2个异步的READ IRP 第一个IRP A进入StartIo例程在里边用KeWaitForSingleObject等待5秒钟,然后IRP B用KeInsertDeviceQueue加入到IRP队列 A进入StartIo例程之前是把中断等级提升为 DISPATCH_LEVEL 了的 但是B还是能够继续执行说明有线程的切换 这里的KeWaitForSingleObject是不是有个一个功能就是 在等待的时候把IRQL等级降低结束等待的时候在还原以前的等级呢?

问题三:在问题二的基础上在应用程序异步READ以后 执行CancelIo函数 取消例程中 将IRP设置为 STATUS_CANCELLED 等到上边的5秒钟等待完毕以后 就是KeRemoveDeviceQueue从IRP队列取出元素 但是运行到这里发生了蓝屏,调用CancelIo的是线程A还是B呢?蓝屏的原因是不是因为 先设置了IRP 在从IRP队列中取出 这样顺序错了造成的呢? 为什么呢?

问题比较多 还请各位高手帮忙解答下 再次谢谢哈
...全文
184 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
曹大夯 2011-12-31
  • 打赏
  • 举报
回复
问题二:
你的线程A和线程B调用的Device Handle是否同一个?一定要确保A和B访问的是同一个Device Object。

问题三:
蓝屏的具体信息是什么?把信息贴出来大家分析一下。
whatday 2011-12-31
  • 打赏
  • 举报
回复
2011最后一天了 自己顶一下 还请各位路人帮忙看看
whatday 2011-12-31
  • 打赏
  • 举报
回复
Driver.h文件如下:

#pragma once

#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.h>
#ifdef __cplusplus
}
#endif

#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号链接名
KDEVICE_QUEUE device_queue; //设备队列
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

// 函数声明

NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp);
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp);
NTSTATUS HelloDDKCleanUp(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp);
whatday 2011-12-31
  • 打赏
  • 举报
回复
应用程序代码如下:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hDevice dd ?
szBuffer db 100 dup (?)
szReadBuffer db 10 dup (?)
hStdOut dd ?
dwBytes dd ?
stOverlap OVERLAPPED <>
hThread dd 2 dup (?)
dwThreadId dd ?

.const
szShow db 'Open Device failed!',0dh,0ah,0
szDevice db '\\.\HelloDDK',0
szShow2 db 'Enter Thread',0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Thread proc uses ebx esi edi,_lParam

invoke lstrlen,offset szShow2
invoke WriteConsole,hStdOut,offset szShow2,eax,offset dwBytes,NULL
invoke CreateEvent,NULL,FALSE,FALSE,NULL
mov stOverlap.hEvent,eax

invoke ReadFile,_lParam,offset szReadBuffer,10,offset dwBytes,offset stOverlap
invoke CancelIo,_lParam
invoke WaitForSingleObject,stOverlap.hEvent,INFINITE;

ret

_Thread endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hStdOut,eax
invoke CreateFile,offset szDevice,GENERIC_READ or GENERIC_WRITE,\
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,NULL
.if eax == INVALID_HANDLE_VALUE
invoke lstrlen,offset szShow
invoke WriteConsole,hStdOut,offset szShow,eax,offset dwBytes,NULL
jmp _Ret
.endif
mov hDevice,eax
invoke CreateThread,NULL,0,offset _Thread,hDevice,0,offset dwThreadId
mov hThread,eax

invoke CreateThread,NULL,0,offset _Thread,hDevice,0,offset dwThreadId
mov dword ptr [hThread+4],eax

invoke WaitForMultipleObjects,2,offset hThread,TRUE,INFINITE

invoke CloseHandle,hThread
invoke CloseHandle,[hThread+4]
invoke CloseHandle,hDevice
_Ret:
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
whatday 2011-12-31
  • 打赏
  • 举报
回复
驱动程序代码如下:
/************************************************************************
* 文件名称:Driver.cpp
* 作 者:张帆
* 完成日期:2007-11-1
*************************************************************************/

#include "Driver.h"


#pragma LOCKEDCODE
VOID
MyStartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pFistIrp
)
{
KdPrint(("Enter MyStartIo\n"));

PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
DeviceObject->DeviceExtension;

PKDEVICE_QUEUE_ENTRY device_entry;

PIRP Irp = pFistIrp;
do
{
KEVENT event;
KeInitializeEvent(&event,NotificationEvent,FALSE);

//等3秒
LARGE_INTEGER timeout;
timeout.QuadPart = -3*1000*1000*10;

//定义一个3秒的延时,主要是为了模拟该IRP操作需要大概3秒左右时间
KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,&timeout);

KdPrint(("Complete a irp:%x\n",Irp));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; // no bytes xfered
IoCompleteRequest(Irp,IO_NO_INCREMENT);

device_entry=KeRemoveDeviceQueue(&pDevExt->device_queue);
KdPrint(("device_entry:%x\n",device_entry));
if (device_entry==NULL)
{
break;
}

Irp = CONTAINING_RECORD(device_entry, IRP, Tail.Overlay.DeviceQueueEntry);
}while(1);

KdPrint(("Leave MyStartIo\n"));
}

/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE
extern "C" NTSTATUS DriverEntry (
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status;
KdPrint(("Enter DriverEntry\n"));

//设置卸载函数
pDriverObject->DriverUnload = HelloDDKUnload;

//设置派遣函数
pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HelloDDKDispatchRoutin;

//创建驱动设备对象
status = CreateDevice(pDriverObject);

KdPrint(("Leave DriverEntry\n"));
return status;
}

/************************************************************************
* 函数名称:CreateDevice
* 功能描述:初始化设备对象
* 参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
* 返回 值:返回初始化状态
*************************************************************************/
#pragma INITCODE
NTSTATUS CreateDevice (
IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;

//创建设备名称
UNICODE_STRING devName;
RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");

//创建设备
status = IoCreateDevice( pDriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pDevObj );
if (!NT_SUCCESS(status))
return status;

pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;

RtlZeroBytes(&pDevExt->device_queue,sizeof(pDevExt->device_queue));
KeInitializeDeviceQueue(&pDevExt->device_queue);

//创建符号链接
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink( &symLinkName,&devName );
if (!NT_SUCCESS(status))
{
IoDeleteDevice( pDevObj );
return status;
}
return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:HelloDDKUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
pDriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
KdPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject;
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pNextObj->DeviceExtension;

//删除符号链接
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName);

pNextObj = pNextObj->NextDevice;
IoDeleteDevice( pDevExt->pDevice );
}
}

/************************************************************************
* 函数名称:HelloDDKDispatchRoutin
* 功能描述:对读IRP进行处理
* 参数列表:
pDevObj:功能设备对象
pIrp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
KdPrint(("Enter HelloDDKDispatchRoutin\n"));

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//建立一个字符串数组与IRP类型对应起来
static char* irpname[] =
{
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
};

UCHAR type = stack->MajorFunction;
if (type >= arraysize(irpname))
KdPrint((" - Unknown IRP, major type %X\n", type));
else
KdPrint(("\t%s\n", irpname[type]));

//对一般IRP的简单操作,后面会介绍对IRP更复杂的操作
NTSTATUS status = STATUS_SUCCESS;
// 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );

KdPrint(("Leave HelloDDKDispatchRoutin\n"));

return status;
}

VOID
OnCancelIRP(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KdPrint(("Enter CancelReadIRP\n"));

//释放Cancel自旋锁
IoReleaseCancelSpinLock(Irp->CancelIrql);

//设置完成状态为STATUS_CANCELLED
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest( Irp, IO_NO_INCREMENT );

KdPrint(("Leave CancelReadIRP\n"));
}

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
KdPrint(("Enter HelloDDKRead\n"));

PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;

//将IRP设置为挂起
IoMarkIrpPending(pIrp);

IoSetCancelRoutine(pIrp,OnCancelIRP);

KIRQL oldirql;
//提升IRP至DISPATCH_LEVEL
KeRaiseIrql(DISPATCH_LEVEL, &oldirql);

KdPrint(("HelloDDKRead irp :%x\n",pIrp));

KdPrint(("DeviceQueueEntry:%x\n",&pIrp->Tail.Overlay.DeviceQueueEntry));
if (!KeInsertDeviceQueue(&pDevExt->device_queue, &pIrp->Tail.Overlay.DeviceQueueEntry))
MyStartIo(pDevObj,pIrp);

//将IRP降至原来IRQL
KeLowerIrql(oldirql);

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

//返回pending状态
return STATUS_PENDING;
}

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧