阅读:3167回复:21
紧急求助:关于Kewaitforsingleobject()问题
问题是这样的:
我没有用桥芯片,直接用FPGA实现PCI协议的。 用事件来实现驱动和应用的同步,所有事件的操作都在驱动中完成。 TOMDRIVER_IOCTL_801_Handler(KIrp I) 中创建事件, TOMDRIVER_IOCTL_802_Handler(KIrp I) 应用程序读数的IOCTL,同时在这里做了等待,用kewaitforsingleobject等待中断来才开始调用memcpy函数。 BOOLEAN CyxdriverDevice::Isr_Irq(void) 中KeSetEvent。 硬件pci协议上做了规定,当硬件接收到足够的数据时,pci发出中断,此时才开始数据传输。 应用程序是多线程的,其中一个线程是专门用作PCI读数的。在该线程中先调用801,再循环调用802读数。 现在出现的问题是,应用程序运行一段时间后就会突然停掉,收数的线程停止了。用打印语句跟踪发现是停在驱动的802的kewaitforsingleobject语句。用DriverWizard往中断寄存器中直接写入中断,跟踪到驱动运行了中断服务程序,但是事件还是没有被激活,仍然停在kewaitforsingleobject函数处。 是不是kewaitforsingleobject这样使用不对呢,还是说会有什么负面影响?以前我是在中断中设置一个信号量,中断来了,设为有效。在802中不断查询该信号量,当其有效时才 才接收数据。不会出现这个问题,就是cpu资源太高,用了EVENT后,CPU资源就降下来了。 能不能帮我看看。我看在你的pdc1000驱动里面也用了kewaitforsingleobject,没出现过 问题,是不是还要进行一些其他的设置呢? 这个问题很急,我调了2天了,都没解决。帮忙看看吧,谢了!! 驱动程序中的相关代码: PKEVENT pEvent; HANDLE hEvent; NTSTATUS CyxdriverDevice::TOMDRIVER_IOCTL_801_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; WCHAR wEventNameBuf[]=L"\\BaseNamedObjects\\SharedEvent"; UNICODE_STRING uEventName; RtlInitUnicodeString(&uEventName,wEventNameBuf); pEvent = IoCreateNotificationEvent(&uEventName,&hEvent); KeResetEvent(pEvent); m_IoPortRange0.outd(4,4026531847); // open 263 door m_IoPortRange0.outd(8,phyadd); // write physical address or memory buffer // 上面两句代码跟我们下面具体的电路设计有关。 I.Information() = 4; return status; } NTSTATUS CyxdriverDevice::TOMDRIVER_IOCTL_802_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; unsigned long reg = 0; unsigned long reg1 = 0; unsigned int time = 0; LARGE_INTEGER OneSecondTimeout; OneSecondTimeout.QuadPart = -1i64 * 1000000i64 * 10i64; do{ KeResetEvent(pEvent); m_IoPortRange0.outd(0,15); KeWaitForSingleObject((PKEVENT)pEvent,Executive,KernelMode,FALSE,&OneSecondTimeout); memcpy((char *)I.IoctlBuffer(),(char *)viradd,1024); I.Information() = 1024; return status; } BOOLEAN CyxdriverDevice::Isr_Irq(void) { KeSetEvent((PKEVENT)pEvent, 0, FALSE); return TRUE; } 应用程序中的相关代码: int door ; UINT PCIThread(LPVOID lpParam) { ULONG nOutput,o2; // Count written to bufOutput unsigned char *data; unsigned long input = 50; int sleep_cnt = 0; int id=0; door = 1; data = (unsigned char *)malloc(2048); if (!DeviceIoControl(hDevice, TOMDRIVER_IOCTL_801, NULL, 0, NULL, 0, &o2, NULL) ) { AfxMessageBox("ERROR: DeviceIoControl801 returns %0x.", GetLastError()); exit(1); } do{ if (!DeviceIoControl(hDevice, TOMDRIVER_IOCTL_802, &input, 4, data, 1024, &nOutput, NULL) ) { AfxMessageBox("ERROR: DeviceIoControl returns %0x.", GetLastError()); exit(1); }else { pDlg->m_myadder+=1024; pDlg->m_lib.q.put(data); for(id=0;id<1024;id++) { if (memcmp(data+id,startcode,3)==0) pDlg->m_myframe++; } } }while(door==1); return 0; } |
|
沙发#
发布于:2004-08-16 08:43
大家说说看吧,谢了
|
|
板凳#
发布于:2004-08-16 22:55
There IS some kind of problems in your implementation.
First, each time you call TOMDRIVER_IOCTL_802_Handler(KIrp I) you use KeResetEvent(pEvent) to reset the event. At this time you may reset the already signaled event to a not signaled state. Second, you set a time out value for KeWaitForSingleObject(). Why you want to do this? Is that reasonable? You wana do this asynchronously? Think about this: What will happen once this KeWaitForSingleObject() timed out? But at a later time the event is signaled. I think you'd better wait for the event in you user level application. You can turn to the OSR article titled "Sharing Is Caring - Sharing Events Between Kernel-User Mode". This article may solve your problem. Hope this can help. Michael |
|
地板#
发布于:2004-08-17 15:21
谢谢piggy!
1、我现在在adddevice()初始化事件KeInitializeEvent( &(pDevice->Event), SynchronizationEvent, FALSE); 801里面相应的操作没了,也没有resetevent()了。 可是还出现应用程序停顿的现象。我的数据源是外面的摄像头, 应用程序是一个播放软件,当播放窗口停住时,人为的激活其他窗口,播放软件就重新开始播放了。不知道是什么原因? 2、我的驱动是基于ds编的。在应用中创建事件后,无法传给驱动程序,ObReferenceObjectByHandle()里面的参数在ds中调用不成功,所以就放弃了这种作法,直接在驱动中完成事件的全部操作了。 还有,你说的那篇文章哪里有,我没找到,呵呵,贴个网址行吗? |
|
地下室#
发布于:2004-08-17 22:36
I think the best way to solve this problem is waitting for the event directly at user level application. Never use event handle in your implementation because handle is thread context specific. You don't need to call ObReferenceObjectByHandle() in you driver. The following is the link to the OSR article.
http://www.osronline.com/article.cfm?id=108 You can also download the sample code of this article. I've implemented this in one of my project. It works fine. I don't know whether this can solve your problem. But at least it can help you. Another suggestion: Using a specific unique name for your event. Don't use L"\BaseNamedObjects\SharedEvent". "SharedEvent" is a very normal name. Some other applications or drivers may have already created the name. Hope this can help you. |
|
5楼#
发布于:2004-08-18 13:33
Thanks piggy !
文章找到了,代码也下了,我用同名事件共享的办法试了。可是应用程序没有得到图像,不知道是不是事件设置不合理。 我在应用程序中PCIWaitEvent = CreateEvent(NULL, TRUE, FALSE, "PCIWaitEvent"); …… WaitForSingleObject(PCIWaitEvent, 1000); ResetEvent(PCIWaitEvent); 在驱动中 RtlInitUnicodeString(&EventName, L"\\BaseNamedObjects\\PCIWaitEvent"); PCIWaitEvent = IoCreateNotificationEvent(&EventName, &PCIWaitEventHandle); 在驱动的Isr_Irq(void)中KeSetEvent( PCIWaitEvent, 0, FALSE); 现在不能得到图像,分析原因可能是事件的状态不对。不知道 关于事件操作的几个函数的参数有没有用对? 请赐教! |
|
6楼#
发布于:2004-08-18 13:54
I think the best way to solve this problem is waitting for the event directly at user level application. Never use event handle in your implementation because handle is thread context specific. You don't need to call ObReferenceObjectByHandle() in you driver. The following is the link to the OSR article. |
|
7楼#
发布于:2004-08-18 22:27
In your user level application:
PCIWaitEvent = CreateEvent(NULL, FALSE, FALSE, "PCIWaitEvent"); /*At here you don't need to manully reset the event */ …… while (TRUE) { // // Now you can just sit back and wait for the driver to signal the event. // You check the event state every 1 seconds... // WaitStatus = WaitForSingleObject(PCIWaitEvent, 1000); if (WaitStatus != WAIT_OBJECT_0) { continue; } else { //do your work at here } } In you driver: RtlInitUnicodeString(&EventName, L"\\BaseNamedObjects\\PCIWaitEvent"); /* 2 \\ rather than 1 \ */ PCIWaitEvent = IoCreateNotificationEvent(&EventName, &PCIWaitEventHandle); if(PCIWaitEvent != NULL) { // // Take a reference out on the object so that // it does not go away if the application // goes away unexpectedly // ObReferenceObject(PCIWaitEvent); status = STATUS_SUCCESS; } else status = STATUS_UNSUCCESSFUL; In Isr_Irq(void), call KeSetEvent( PCIWaitEvent, 0, FALSE); Hope this can help you. |
|
8楼#
发布于:2004-08-19 08:55
用户被禁言,该主题自动屏蔽! |
|
9楼#
发布于:2004-08-20 09:27
to piggy:
再次感谢!根据你的建议改了,还是有问题。接收的数据还是不对,cpu占用将近100%,而且还是存在停顿的现象。看来,这些还不是导致停顿现象的主要原因。唉…… to tom.cat: 谢谢!不过还是不太清楚“IRP串行”,能不能推荐一些相关的文章或是例子? |
|
10楼#
发布于:2004-08-20 13:36
对驱动IRQL的概念糊里糊涂的,不知道我上面代码中的
TOMDRIVER_IOCTL_802_Handler(KIrp I) 是运行在哪个级别的? 不知道是不是kewaitforsingleobject()不能运行在改IRQL? 唉,实在想不出还有什么地方会出错的了。 大家帮帮帮忙吧,分不够可以再加的! |
|
11楼#
发布于:2004-08-20 13:56
用 KeGetCurrentIrql()测试过了,是在PASSIVE_LEVEL 下的。
看来这个地方也是没有问题的,唉,问题呀,你到底出在哪里 呀 :( |
|
12楼#
发布于:2004-08-20 15:56
用 KeGetCurrentIrql()测试过了,是在PASSIVE_LEVEL 下的。 是呀,你的线程运行在PASSIVE_LEVEL ,而中断处理是在DPC运行的,如果中断积累的太多,DPC的事情都做不完,PASSIVE_LEVEL 的线程能得到CPU时间吗。 DDK的每给例子都对这个处理的很好,为什么要用DS,麻烦。 |
|
13楼#
发布于:2004-08-20 16:08
莫非真的得用DDK?现在时间比较紧,不知道ddk自带的例子中有没有
关于pci驱动的?看了一下,好像只有usb的。还有walt only 的那本 Programming the Microsoft WDM,是不是都要看呀,好像很多,能 不能推荐一些比较相关的章节呀?小妹在此感谢所有回帖的大哥大姐 了! |
|
14楼#
发布于:2004-08-20 16:19
莫非真的得用DDK?现在时间比较紧,不知道ddk自带的例子中有没有 至少DDK例子的构架很完备,DDK里有网卡的驱动,和PCI的驱动应该是很接近的了,而且网卡处理的数据量也不小呀。只是NdisXXXX之类的函数应该换成相应的WDM函数。有你上边的经验,改起来应该很快的。 |
|
15楼#
发布于:2004-08-20 16:44
好的,我先看看,不过,还是希望那个停顿的问题能在ds上解决啊
|
|
16楼#
发布于:2004-08-20 17:01
好的,我先看看,不过,还是希望那个停顿的问题能在ds上解决啊 可以,你把处理数据的部分拿到DPC去。看看。 |
|
17楼#
发布于:2004-08-20 17:13
数据的处理是在应用程序中进行的,驱动Isr_Irq(void)很简单,只有kesetevent()。
还有,那个DDK里有网卡的驱动是不是:\NTDDK\src\network\ndis\e100bex? 我觉得ndis跟WDM的风格还是有很大不同的。不知道:\NTDDK\src\wdm 文件夹中有没有跟pci比较相关的例子?再谢! |
|
18楼#
发布于:2004-08-20 17:24
问题说的简单点,就是你那个KeWaitForSingleObject,他运行的IRQL级别太低,应该提高他的IRQL。
另:数据到RING3处理,少量的数据没有什么问题,如果是大量数据,要提高效率,是要做很多工作的,否则慢的让人不能接受,而且会丢包。 至于别的DDK例子我没有看过,本站也有别人贴的PCI的例子,你可以搜索一下。 |
|
19楼#
发布于:2004-08-20 17:36
谢谢asmsys 大侠!
你是说我可以在调用kewaitforsingleobjct()前,先调用KeRaiseIrql()提高IRQL,跳出wait后再恢复为PASSIVE_LEVEL 吗? 不知道这么做会不会有什么副作用? |
|
上一页
下一页