阅读:1553回复:15
大家看看我的代码有错误码?为什么偶尔蓝屏??
下面是我用DS写的ISA卡的NT式的驱动的部分程序,运行在WIN2000上,中断方式获得数据,具体工作原理是:
在驱动的初始化例程(DDK里就是驱动入口点例程),驱动分配一个非分页内存Buf用来在中断延迟例程里存放从端口读到的数据,驱动程序通过一个DeviceIoCtl把该内存影射后的用户虚拟地址传递给应用层。 应用层分配一个事件对象通过DeviceIoCtl传递给驱动层,在中断延迟里驱动读完端口设置事件对象为有效,来通知应用, 可以操作这个缓冲里的数据了。 就是通过这样的方式达到硬件和驱动,驱动和应用通信。 我下面给出了四个例程,分别是:分配非分页内存的驱动初始化例程(部分);传递事件对象例程;中断延迟例程;中断例程。 各位看一看,中断和中断延迟调用部分的代码规范吗?我现在的问题是驱动运行的时候很不稳定,偶尔发生蓝屏的现象, SOFTICE 弹出以下的提示: Break due to Page Fault(0Eh) Fault=0003 MSR LastExceptionFromIp=00000000 MSR LastExecptionToIp=00000000 另外我用DriverMonitor还看到这样一条提示: An underrun error occured in memory block f9d6dc30. 这个没导致蓝屏,只是经常提示 //////////////////////////////////////////////////////////////////////// // 初始化函数,建立设备的资源请求对象,向系统申请资源 ///////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::InitResources(void) { …………………… …………………… //分配中断延迟调用例程里驱动要使用的缓冲 Buf=new(NonPagedPool)UCHAR(68); …………………… …………………… } ////////////////////////////////////////////////////////////////////////// ////接收来自应用层发来的事件对象 ////采用缓冲I/O方式 ////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::EVENT_IOCTL_800_Handler(KIrp I) { t << "Entering JiemaDevice::EVENT_IOCTL_800_Handler, " << I << EOL; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); HANDLE hEvent=*(HANDLE*)I.IoctlBuffer(); m_pEvent=new(NonPagedPool)KEvent(hEvent); NTSTATUS status=(m_pEvent!=NULL)?STATUS_SUCCESS:STATUS_INSUFFICIENT_RESOURCES; I.Information() =0; I.Status() = status; return status; } /////////////////////////////////////////////////////////////////////// // 中断延迟处理程序 // 用事件对象来通知应用程序,中断到来,数据准备好,可以// 读数据了 //////////////////////////////////////////////////////////////////////// VOID JiemaDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2) { m_IoPortRange1.inw(0); m_IoPortRange1.inw(2); ///////////////////////////////////////////////////////////////////////// ///////从端口对象1接收28路解码数据的第1-16路///////////////////////////// for (ULONG i=4;i<32;i=i+2) { m_IoPortRange1.inw(i,(PUSHORT)Buf+i/2-2,1); } //////////////////////////////////////////////////////////////////////// ///////从端口对象2接收28路解码数据的第17-24路/////////////////////////// //////////////////////////////////////////////////////////////////////// for(ULONG j=0;j<16;j=j+2) { m_IoPortRange2.inw(j,(PUSHORT)Buf+14+j/2,1); } //////////////////////////////////////////////////////////////////////// ///////从端口对象3接收28路解码数据的第25-28路////////////////////////// for(ULONG l=0;l<7;l=l+2) { m_IoPortRange3.inw(l,(PUSHORT)Buf+22+l/2,1); } m_IoPortRange3.inw(10,(PUSHORT)Buf+26,1); m_IoPortRange3.inw(12,(PUSHORT)Buf+27,1); //////////////////////////////////////////////////////////////////////// //////// 从端口对象4接收6个字的时码数据////////////////////////////// for(ULONG w=0;w<12;w=w+2) { m_IoPortRange4.inw(w,((PUSHORT)Buf)+28+w/2,1); } //设置事件对象为有效,通知应用层可以读该缓冲区了 m_pEvent->Set(); } //////////////////////////////////////////////////////////////////////// // 中断处理程序 // 确认中断的发生,统计中断次数 //////////////////////////////////////////////////////////////////////// BOOLEAN JiemaDevice::Isr_Irq(void) { m_DpcFor_Irq.Request(NULL, NULL); return TRUE; } |
|
|
沙发#
发布于:2004-02-25 19:21
我想是中断的问题吧,在中断例程应该先判断一下是不是自己的硬件产生的中断
|
|
板凳#
发布于:2004-02-25 19:28
谢谢楼上大哥的回答,我想ISA卡的中断,是固定的,也就是独占的,我能成功申请到我的板卡使用的中断,那么当我的板卡中断到来的时候,就能自动进入我的中断服务例程,我想这个没什么问题吧,我觉得是内存的问题,但实在是找不到内存出错的地方!
真是着急! |
|
|
地板#
发布于:2004-02-25 19:35
ISA的中断也是通过8259A中断控制寄存器控制的
所以它还是一个共享的中断 |
|
地下室#
发布于:2004-02-25 19:40
我做PCI也是遇到和你一样的问题
就是判断了中断是不是自己的硬件产生的后才没再出现 |
|
5楼#
发布于:2004-02-25 19:42
但是我的主板上使用我板卡中断号的设备只有我自己设计的板卡,所以不存在共享的问题,所以也不需要判断。
|
|
|
6楼#
发布于:2004-02-25 19:48
我也不明白,只是把我的体会说一下
像我的pci也是那样子的,你可以试试看 |
|
7楼#
发布于:2004-02-25 19:52
我做PCI也是遇到和你一样的问题 我认为PCI 的中断资源是共享的,也就是同一个中断号可能被多个设备使用,但在一个时间点上只能被一个设备使用,所以需要判断是哪个设备发来的中断。 ISA的中断是独占的,我修改了主板的BIOS把我板卡需要的中断号IRQ5的设置成: PnP/PCI configurations -> Resources controlled by -> manual -> IRQ -> IRQ5 assigned to -> legacy ISA 这样就不需要判断是不是我自己的设备来的中断了。 |
|
|
8楼#
发布于:2004-02-25 19:53
我也不明白,只是把我的体会说一下 你能详细说说的你的PCI的驱动,在用SOFTICE调试的时候出现的是什么样的错误吗?? 写出它的错误提示。 谢谢! |
|
|
9楼#
发布于:2004-02-26 15:22
顶!
|
|
|
10楼#
发布于:2004-02-27 08:29
我也帮你顶顶,说不定会有人旁观者清。
但凡驱动引起的蓝屏,99%都是因为在驱动中访问了不存在的内存地址所致。 |
|
11楼#
发布于:2004-02-27 09:28
我也帮你顶顶,说不定会有人旁观者清。 我也是这么认为的,但我的程序里中断例程和中断延迟调用里,对自己用NEW操作符在堆里分配的非分页内存Buf的操作,从语法上说没产生越界,那什么地方访问了不存在的内存地址呢?Buf的删除我放在了Shtudown例程里,也就是只有在系统关闭的时候,我才真正使这个内存无效。 |
|
|
12楼#
发布于:2004-02-27 13:47
把Buf的地址打印看看是不是和riverMonitor显示underrun的地址一样
既然shutdown了无所谓释放内存了 |
|
13楼#
发布于:2004-02-27 14:12
把Buf的地址打印看看是不是和riverMonitor显示underrun的地址一样 在中断延迟里读端口之前加上这个: t<<"Buf address is:"<<(ULONG)Buf<<"\n"; 这样做可以吧? |
|
|
14楼#
发布于:2004-02-27 19:08
申请内存成功了就可以打印了,一次足矣
|
|
15楼#
发布于:2004-02-27 20:36
我刚才打印了申请到的Buf地址,是f9f84aa8,softice 显示的信息这次没有内存溢出。但在关机的时候,弹出错误:
Break Due to KeBugCheckEx(Unhandled kernel modle exception) Error=c2(BAD POOL CALLER) P1=7;P2=b8a;P3=f9f84ac0,P4=f9f84ac8 释放了已经释放的内存,f9f84ac0是被释放的内存池的头地址,我真的闹部明白,我的Buf申请到了68字节,f9f84ac0正是我申请的Buf内部的一个地址,在关闭之前我没释放过,为什么会提示我有这样的错误呢?? |
|
|