阅读:1942回复:11
紧急求助!
项目快结束,才发现这个问题.特请教各位多谢了!
环境是 win2000, VC60 我给一个ISA卡写了一个Driver,通过和App共享内存获得数据. 当中断到时,Driver通过Event通知App,App从共享内存获得数据,计算后App再实时显示曲线. 但现在问题是当通讯时,如果拖动App,App里的等待数据的线程会挂起,或者App运行时如果启动另一个大些程序,App也会丢失部分的数据! 请问您有好的办法吗? |
|
最新喜欢:flyfox
|
沙发#
发布于:2001-10-29 16:16
说白了你这样的驱动程序与应用程序同步的方法不可能实现.
你可以在驱动程序中将它写到文件中去,这样数据不会丢失,但是也不可能实现实时处理,因为Windows系统都不支持实时处理. [peng-416 编辑于 2001-10-29 16:19] |
|
板凳#
发布于:2001-10-30 11:02
我采用把App和等待线程的优先级提高的办法,使等待线程达到33级
情况好了一些,但还是有丢的! 如果把写文件放到driver中,那又如何实时显示呢?应用层和核心层文件能共享吗? |
|
|
地板#
发布于:2001-10-30 11:44
这种情况下本不允许再有其它的大程序的运行。
对于数据的丢失,你肯定问题出在app中而不是driver中。看看提高一下你driver的运行的IRQL试试。 对于共享内存,可申请两块或多块试试,注意不要一次申请太大的内存块。或者干脆去掉共享内存,直接将采样写入app传入的内存中 |
|
|
地下室#
发布于:2001-10-30 14:25
我说的共享内存是把数据采集板上的采集数据ROM转到App中的,
我试试你说的driver提高运行的IRQL! 先谢谢你! |
|
|
5楼#
发布于:2001-10-30 15:22
你可以先统计一下,是driver丢了数据,还是app丢了
数据。 我估计是app而不是driver |
|
6楼#
发布于:2001-10-31 14:45
Driver没有采数,只是在DPC中重置Event通知App, App在去共享内存采数!
如果没有拖放,和其它事件,就没有数据的丢失! 提高IRQL好像没有用! |
|
|
7楼#
发布于:2001-11-01 18:32
I had ever joint a project. The most important task is to
transfer the hardware data to user buffer(application buffer) and display it REALTIME. We use PCI chip to transfer data. And the os is WIN2000. To display data realtime in win2000, the most important thing is: transfer the data as quickly as you can. As you say, you often lost your data. It don't not surprise me.We met the issue ever. You problem can't be solved easily. First of all, ISA is slower than PCI. You can't change your hardware device, do you? Tell you how we solve the problem: 1. Firstly we use copy to transfer data and we find we will lost much data. 2. Then we use master DMA to realize it. It seems we succeed. But we meet many other issures. I won't talk much about it. May you can change your device. Or you can move your data to user buffer by DMA method. Raising the IRQL is also a working method. Or map you ROM into user memory( Microsoft don't recomment it). of course your PC should have enough memory.hehe, In a word, if you can raise your transfer speed. I believe you will not lost any data. Wish you best luck! |
|
|
8楼#
发布于:2001-11-02 16:13
非常谢谢您的提示!
我的问题可能是在APP层,我正在用缓冲区试试看能不能提高App的效率! 再次感谢! |
|
|
9楼#
发布于:2001-11-05 20:03
不用缓存,对事件的等待也会出问题。
os的任务多时,底层不停的KeSetEvent, but in app, no more time to process the WaitSingleObject function, thus, the notification events have been lost.... not th isa card's issues. u can refrence a examples : debugprint monitor. (app) debugprint driver. (driver) debugprint listener. (data & message listener function in drivers) here, u can find the LIST_ENTRY structure is very useful and powerful in the ADC driver(s). it is a soft FIFO no length limits! FIFO: ( First in , First Out). [gxzbme 编辑于 2001-11-05 20:05] |
|
10楼#
发布于:2001-11-06 09:26
It's a good suggestion!
Can u tell me where I can get this examples ? Thanks again! |
|
|
11楼#
发布于:2001-11-12 14:39
This is a example create by driverwork wizard:
driver : Inputmsg.cpp, Inputmsg.h; InputMsgDevice.cpp, InputMsgDeviceh function.h App : Test_Inputmsg.cpp please copy into vc6 for view. u must recode the InputMsgRead dispatch rountine. and delete the InputMsgWrite dispatch function. u can create a system thread for read date from ur ISA card. in this thread, use a dead loop to insert new data read from the card to the list tail, and in irp read dispatch rountine, remove a list node from the list head. remeber, u must init the list and spinlock in device initial rountine. have a good luck! gxzbme +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Test_InputMsg.cpp #include <stdlib.h> #include <stdio.h> #include <windows.h> typedef void VOIDFUNC(); void CloseIfOpen(void); typedef struct _Event { ULONG ID; char buf[255]; } EventMsg; HANDLE hDevice = INVALID_HANDLE_VALUE; char *sLinkName = "\\\\.\\IkonInputMsgDevice0"; HANDLE OpenByName(void) { // Create a handle to the driver return CreateFile(sLinkName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); } void CloseIfOpen(void) { if (hDevice != INVALID_HANDLE_VALUE) { // Close the handle to the driver if (!CloseHandle(hDevice)) { printf("ERROR: CloseHandle returns %0x.\n", GetLastError()); } hDevice = INVALID_HANDLE_VALUE; } } EventMsg eventmsg = { 0, "I am Monster!" }; EventMsg event1 = { 1, " I am Gong xinzhou!" }; int __cdecl main(int argc, char *argv[]) { int nArgIndex; // Walk through command line arguments int nArgIncrement = 0; int val; ULONG nWritten,nRead; printf("Test application Test_InputMsg starting...\n"); hDevice = OpenByName(); if (hDevice == INVALID_HANDLE_VALUE) { printf("ERROR opening device: (%0x) returned from CreateFile\n", GetLastError()); Exit(1); } else { printf("Device found, handle open.\n"); } // Parse the command line printf("eventmsg: ID=%2d, Buf=%s\n",eventmsg.ID,eventmsg.buf); WriteFile(hDevice, &eventmsg, sizeof(EventMsg), &nWritten, NULL); ReadFile(hDevice, &event1, sizeof(EventMsg), &nRead, NULL); printf("event1: ID=%2d, Buf=%s\n",event1.ID,event1.buf); CloseIfOpen(); return 0; } //////////////////////////////////////////////////////////// // InputMsg.cpp #define VDW_MAIN #include <vdw.h> #include "function.h" #include "InputMsg.h" #include "InputMsgDevice.h" #pragma hdrstop("InputMsg.pch") POOLTAG DefaultPoolTag('upnI'); KTrace t("InputMsg"); #pragma code_seg("INIT") DECLARE_DRIVER_CLASS(InputMsg, NULL) NTSTATUS InputMsg::DriverEntry(PUNICODE_STRING RegistryPath) { NTSTATUS status; // Status of device creation t << "In DriverEntry\n"; UNREFERENCED_PARAMETER(RegistryPath); int Unit; Unit = 0; InputMsgDevice* pInputMsgDevice; pInputMsgDevice = new ( static_cast<PCWSTR>(KUnitizedName(L"InputMsgDevice", Unit)), FILE_DEVICE_UNKNOWN, static_cast<PCWSTR>(KUnitizedName(L"InputMsgDevice", Unit)), 0, DO_BUFFERED_IO ) InputMsgDevice(); if (pInputMsgDevice == NULL) { t << "Error constructing device InputMsgDevice" << EOL; return STATUS_INSUFFICIENT_RESOURCES; } status = pInputMsgDevice->ConstructorStatus(); if (!NT_SUCCESS(status)) { t << "Error creating device InputMsgDevice, status " << (ULONG) status << EOL; delete pInputMsgDevice; return status; } return STATUS_SUCCESS; } #pragma code_seg() VOID InputMsg::Unload(VOID) { t << "Unload called\n"; KDriver::Unload(); } // InputMsgDevice.cpp // Implementation of InputMsgDevice device class #include <vdw.h> #include "InputMsg.h" #include "InputMsgDevice.h" #pragma warning(disable:4065) // Allow switch statement with no cases extern KTrace t; // Global driver trace object InputMsgDevice::~InputMsgDevice() { delete m_RegPath; } #pragma code_seg("INIT") InputMsgDevice::InputMsgDevice(ULONG Unit) : KDevice() { if ( ! NT_SUCCESS(m_ConstructorStatus) ) { t << "Failed to create device InputMsgDevice unit number " << Unit << " status " << (ULONG) m_ConstructorStatus << EOL; return; } m_Unit = Unit; m_RegPath = CreateRegistryPath(L"InputMsgDevice", Unit); if (m_RegPath == NULL) { t << "Failed to create registry path\n"; m_ConstructorStatus = STATUS_INSUFFICIENT_RESOURCES; return; } m_pDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; m_pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; KeInitializeSpinLock(&EventListLock); KeInitializeSpinLock(&ReadIrpLock); InitializeListHead(&EventList); ReadIrp = NULL; } #pragma code_seg() VOID InputMsgDevice::InputMsgCancelIrp(KIrp I) { KIRQL irql; KeAcquireSpinLock(&ReadIrpLock,&irql); if( I = ReadIrp) { ReadIrp = NULL; } KeReleaseSpinLock(&ReadIrpLock,irql); // Whatever Irp it is, just cancel it I.Complete(STATUS_CANCELLED,0); } BOOLEAN InputMsgDevice::ReadEvent(KIrp I) { // Try to remove Event from EventList PLIST_ENTRY pListEntry = ExInterlockedRemoveHeadList(&EventList, &EventListLock); if( pListEntry==NULL) return false; // Get event as INPUTMSG_EVENT PINPUTMSG_EVENT pEvent = CONTAINING_RECORD( pListEntry, INPUTMSG_EVENT, ListEntry); // Get length of event data ULONG EventDataLen = pEvent->Len; // Copy data to I and complete it RtlCopyMemory(I.BufferedReadDest(),pEvent->EventData, EventDataLen); I.Information() = EventDataLen; I.SetCancelRoutine(NULL); I.Complete(STATUS_SUCCESS); // Free event memory ExFreePool(pEvent); return true; } NTSTATUS InputMsgDevice::Read(KIrp I) { t << "Entering read, " << I; // Always ok to read 0 elements if (I.ReadSize() == 0) { I.Information() = 0; return I.Complete(STATUS_SUCCESS); } NTSTATUS status = STATUS_SUCCESS; //////////////////////////////////////////////////////////////////////////////// // Only one listening read allowed at a time. KIRQL irql; KeAcquireSpinLock(&ReadIrpLock,&irql); if( ReadIrp!=NULL) { KeReleaseSpinLock(&ReadIrpLock,irql); return I.Complete(STATUS_UNSUCCESSFUL); } // See if there's data available if( ReadEvent(I)) { KeReleaseSpinLock(&ReadIrpLock,irql); return STATUS_SUCCESS; } // No event is available, queue this read Irp ReadIrp = I; KeReleaseSpinLock(&ReadIrpLock,irql); // Mark Irp as pending and set Cancel routine I.Information() = 0; I.MarkPending(I.Status()); I.SetCancelRoutine(LinkTo(InputMsgCancelIrp) ); return STATUS_PENDING; //////////////////////////////////////////////////////////////////// } NTSTATUS InputMsgDevice::Write(KIrp I) { t << "Entering write, " << I; if (I.WriteSize() == 0) { I.Information() = 0; return I.Complete(STATUS_SUCCESS); } NTSTATUS status = STATUS_SUCCESS; /////////////////////////////////////////////////////////////////////////////////// ULONG WriteLen = I.WriteSize(CURRENT); // Copy write data into an event ULONG Len = sizeof(LIST_ENTRY)+sizeof(ULONG)+WriteLen; PINPUTMSG_EVENT pEvent = (PINPUTMSG_EVENT)ExAllocatePool(NonPagedPool,Len); if( pEvent==NULL) { return I.Complete(STATUS_INSUFFICIENT_RESOURCES,0); } pEvent->Len = WriteLen; RtlCopyMemory( pEvent->EventData, I.BufferedWriteSource(), WriteLen); // Insert event into event list ExInterlockedInsertTailList(&EventList,&pEvent->ListEntry,&EventListLock); // If read pending, then read it KIRQL irql; KeAcquireSpinLock(&ReadIrpLock,&irql); if( ReadIrp!=NULL) if( ReadEvent(I)) { ReadIrp = NULL; } KeReleaseSpinLock(&ReadIrpLock,irql); /////////////////////////////////////////////////////////////// I.Information() = WriteLen; return I.Complete(status); } NTSTATUS InputMsgDevice::Create(KIrp I) { t << "Entering Create, " << I; I.Information() = 0; return I.Complete(STATUS_SUCCESS); } NTSTATUS InputMsgDevice::Close(KIrp I) { t << "Entering Close, " << I; I.Information() = 0; return I.Complete(STATUS_SUCCESS); } // InputMsgDevice.h // #ifndef __InputMsgDevice_h__ #define __InputMsgDevice_h__ typedef struct _INPUTMSG_EVENT { LIST_ENTRY ListEntry; ULONG Len; UCHAR EventData[1]; } INPUTMSG_EVENT, *PINPUTMSG_EVENT; class InputMsgDevice : public KDevice { public: SAFE_DESTRUCTORS; InputMsgDevice(ULONG Unit=0); ~InputMsgDevice(); public: DEVMEMBER_DISPATCHERS #ifdef __COMMENT_ONLY virtual NTSTATUS Close(KIrp I); // COMMENT_ONLY virtual NTSTATUS Create(KIrp I); // COMMENT_ONLY virtual NTSTATUS Read(KIrp I); // COMMENT_ONLY virtual NTSTATUS Write(KIrp I); // COMMENT_ONLY #endif BOOLEAN ReadEvent(KIrp I); // VOID InputMsgCancelIrp(KIrp Irp); DEVMEMBER_CANCELIRP (InputMsgDevice, InputMsgCancelIrp) protected: ULONG m_Unit; KUnitizedName * m_RegPath; KIrp ReadIrp; // "Read queue" of 1 IRP KSPIN_LOCK EventListLock; KSPIN_LOCK ReadIrpLock; // Spin lock to guard access to ReadIrp LIST_ENTRY EventList; }; #endif // __InputMsgDevice_h__ // InputMsg.h // #ifndef __InputMsg_h__ #define __InputMsg_h__ #define EOL "\n" class InputMsg : public KDriver { SAFE_DESTRUCTORS public: virtual VOID Unload(VOID); virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath); }; #endif // __InputMsg_h__ |
|