IoAllocateIrp创建的IRP用IoFreeIrp删除蓝屏的问题

yongbuyanbai88 2011-12-04 09:28:09
本人在看windows驱动开发技术详解,作者在第十一章提到用IoAllocateIrp内核函数创建IRP时,需要程序员调用IoFreeIrp内核函数删除IRP对象。
下面是驱动程序B调用驱动程序A的一段代码:
驱动B的部分代码:
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
{
KdPrint(("DriverB:Enter B HelloDDKRead\n"));
NTSTATUS ntStatus = STATUS_SUCCESS;

UNICODE_STRING DeviceName;
RtlInitUnicodeString( &DeviceName, L"\\Device\\MyDDKDeviceA" );

PDEVICE_OBJECT DeviceObject = NULL;
PFILE_OBJECT FileObject = NULL;
//得到设备对象指针
ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);

KdPrint(("DriverB:FileObject:%x\n",FileObject));
KdPrint(("DriverB:DeviceObject:%x\n",DeviceObject));

if (!NT_SUCCESS(ntStatus))
{
KdPrint(("DriverB:IoGetDeviceObjectPointer() 0x%x\n", ntStatus ));
ntStatus = STATUS_UNSUCCESSFUL;
// 完成IRP
pIrp->IoStatus.Status = ntStatus;
pIrp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
KdPrint(("DriverB:Leave B HelloDDKRead\n"));

return ntStatus;
}

KEVENT event;
KeInitializeEvent(&event,NotificationEvent,FALSE);

PIRP pNewIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
KdPrint(("pNewIrp->UserEvent :%x\n",pNewIrp->UserEvent));
pNewIrp->UserEvent = &event;

IO_STATUS_BLOCK status_block;
pNewIrp->UserIosb = &status_block;
pNewIrp->Tail.Overlay.Thread = PsGetCurrentThread();

//因为DriverA是BUFFER IO设备
pNewIrp->AssociatedIrp.SystemBuffer = NULL;

KdPrint(("DriverB:pNewIrp:%x\n",pNewIrp));

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(pNewIrp);
stack->MajorFunction = IRP_MJ_READ;
stack->MinorFunction=IRP_MN_NORMAL;//0
stack->FileObject = FileObject;

//调用DriverA驱动
NTSTATUS status = IoCallDriver(DeviceObject,pNewIrp);

if (status == STATUS_PENDING) {
status = KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE, // Not alertable
NULL);
KdPrint(("STATUS_PENDING\n"));
}

ObDereferenceObject( FileObject );
IoFreeIrp(pNewIrp);//该句有问题!!!!

ntStatus = STATUS_SUCCESS;
// 完成IRP
pIrp->IoStatus.Status = ntStatus;
pIrp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
KdPrint(("DriverB:Leave B HelloDDKRead\n"));
return ntStatus;
}

驱动A中对相应IRP响应函数先把IRP挂起,然后定时三秒后结束IRP,部分代码如下:

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

PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;

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

//将挂起的IRP记录下来
pDevExt->currentPendingIRP = pIrp;

//定义3秒后将IRP_MJ_READ的IRP完成
ULONG ulMicroSecond = 3000000;

//将32位整数转化成64位整数
LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10*ulMicroSecond);

KeSetTimer(
&pDevExt->pollingTimer,
timeout,
&pDevExt->pollingDPC );

KdPrint(("DriverA:Leave A HelloDDKRead\n"));

//返回pending状态
return STATUS_PENDING;
}

#pragma LOCKEDCODE
VOID OnTimerDpc( IN PKDPC pDpc,
IN PVOID pContext,
IN PVOID SysArg1,
IN PVOID SysArg2 )
{
PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

PIRP currentPendingIRP = pdx->currentPendingIRP;

KdPrint(("DriverA:complete the Driver A IRP_MJ_READ irp!\n"));

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

问题是上面驱动B的红色标注的代码IoFreeIrp(pNewIrp);有这行代码会蓝屏,去掉这行代码,程序没有蓝屏错误,张帆的书上没有这行代码,但是配套光盘上面有。查阅ddk帮助,好像说必须设置完成例程用来释放IRP,初学驱动,刚开始看书,完成例程我还没有看到,请各位指点下,解释下为什么蓝屏,多谢。
...全文
414 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
DemonDante 2012-02-02
  • 打赏
  • 举报
回复
既然上层可以删除了,那为什么还会蓝屏啊~
yongbuyanbai88 2011-12-06
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 fanggai 的回复:]

引用 4 楼 yongbuyanbai88 的回复:

引用 3 楼 fanggai 的回复:

Irp发往下层驱动了,你就不应该再操作它了 如果需要再操作它,就注册完成例程,下层驱动完成对这个IRP的处理并向上走时,检测发现有完成例程,就会调用完成例程,这时你的驱动才能继续操作IRP
因此IoFreeIrp(pNewIrp);这一句需要放在完成例程里。


不胜感激,再顺便问……
[/Quote]

好的,多谢,结贴了。
gfang 2011-12-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yongbuyanbai88 的回复:]

引用 3 楼 fanggai 的回复:

Irp发往下层驱动了,你就不应该再操作它了 如果需要再操作它,就注册完成例程,下层驱动完成对这个IRP的处理并向上走时,检测发现有完成例程,就会调用完成例程,这时你的驱动才能继续操作IRP
因此IoFreeIrp(pNewIrp);这一句需要放在完成例程里。


不胜感激,再顺便问一下,上面的程序中,IRP已经被下层驱动结束了,上层还不能删……
[/Quote]
可以。下层驱动A完成IRP后,若上层驱动B注册了完成例程,则B在完成例程里可以删除该IRP(条件是该IRP是B创建的,不然B不应该删除)。
yongbuyanbai88 2011-12-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 fanggai 的回复:]

Irp发往下层驱动了,你就不应该再操作它了 如果需要再操作它,就注册完成例程,下层驱动完成对这个IRP的处理并向上走时,检测发现有完成例程,就会调用完成例程,这时你的驱动才能继续操作IRP
因此IoFreeIrp(pNewIrp);这一句需要放在完成例程里。
[/Quote]

不胜感激,再顺便问一下,上面的程序中,IRP已经被下层驱动结束了,上层还不能删除该IRP吗?
gfang 2011-12-05
  • 打赏
  • 举报
回复
Irp发往下层驱动了,你就不应该再操作它了 如果需要再操作它,就注册完成例程,下层驱动完成对这个IRP的处理并向上走时,检测发现有完成例程,就会调用完成例程,这时你的驱动才能继续操作IRP
因此IoFreeIrp(pNewIrp);这一句需要放在完成例程里。
yongbuyanbai88 2011-12-04
  • 打赏
  • 举报
回复
多谢大师……

[Quote=引用 1 楼 woshi_ziyu 的回复:]

帮顶
[/Quote]
woshi_ziyu 2011-12-04
  • 打赏
  • 举报
回复
帮顶
内容概要:本文围绕超导磁能储存系统(SMES)的建模与仿真展开,基于Simulink平台构建系统级动态仿真模型,涵盖超导线圈、功率转换系统(PCS)以及核心控制策略等关键模块。研究重点在于分析SMES在电网中实现快速能量存储与释放的能力,验证其在提升电力系统稳定性、抑制功率波动方面的有效性,尤其针对新能源发电带来的间歇性与波动性问题提供了有效的解决方案。通过仿真手段深入探讨系统的动态响应特性,为优化控制算法的设计与应用提供可靠的技术支撑。; 适合人群:适用于具备电力系统、自动控制理论或能源存储技术背景,熟悉Simulink仿真环境的科研人员、工程技术人员及研究生;同时适合有志于开展新型储能技术仿真研究的高年级本科生参考学习。; 使用场景及目标:①深入理解超导磁能储存系统的基本结构、工作原理及其在电力系统中的应用场景;②掌握在Simulink中搭建复杂电力电子与控制系统联合仿真模型的方法;③研究SMES在电网调频、电压支撑、瞬时功率补偿等典型工况下的动态性能表现;④为后续先进控制策略(如PID、模糊控制、现代控制理论等)的优化设计与验证提供仿真试验平台。; 阅读建议:建议读者结合文中模型逐步动手搭建仿真系统,重点关注各功能模块的参数设置与信号接口匹配,配合具体案例进行仿真调试,深入理解控制逻辑与系统动态行为之间的内在联系,并可进一步拓展至与其他储能形式(如锂电池、飞轮储能)的性能对比研究,以深化对不同类型储能技术特点的认知。
内容概要:本文围绕“考虑火-储联合调频(火电机组-混合储能)的协同控制策略”展开研究,提出一种基于Matlab仿真的协同控制方法,旨在提升电力系统频率调节的快速性与稳定性。通过构建火电机组与混合储能(如蓄电池、飞轮等)的联合调频模型,设计合理的功率分配机制与控制策略,充分发挥火电的持续调节能力与储能的快速响应优势,有效应对电网负荷波动与频率偏差。文中结合改进信号分解算法(如ICEEMDAN)与优化算法(如GWO),实现对调频信号的精准分频与储能单元的优化调度,提高系统整体调频效率与经济性。; 适合人群:具备一定电力系统基础知识和Matlab编程能力,从事新能源并网、电力系统稳定控制、储能技术应用等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于研究火电机组与混合储能在电网一次调频、二次调频中的协同作用机制;②为实际电力系统中储能配置与调频控制策略设计提供仿真验证平台与理论支持;③支撑相关课题研究、学术论文撰写及工程项目前期论证。; 阅读建议:建议结合Matlab代码深入理解控制算法实现细节,重点关注功率分配逻辑、信号分解过程与优化算法参数设置,并可通过修改系统参数进行对比仿真,以加深对协同控制效果的认识。

21,620

社区成员

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

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