阅读:1726回复:4
驱动程序如何发消息给应用程序?
我想利用事件实现驱动程序向应用程序发消息。
我设想在DeviceIocontrol里面分配事件,在延迟中断里设置事件。 这样可行吗?应用程序如何设计去配合?有例子源码吗? 送分!送分! |
|
最新喜欢:yuanyu... |
沙发#
发布于:2003-07-29 18:02
1、先由应用程序创建一个事件,然后通过DEVICEIOCONTOL将该事件的句柄传给驱动,最后再创建一个辅助线程来查询该事件。
如DS中的例子所写: // testintr.cpp - application for interrupt demo driver //============================================================================= // // Compuware Corporation // NuMega Lab // 9 Townsend West // Nashua, NH 03060 USA // // Copyright (c) 1998 Compuware Corporation. All Rights Reserved. // Unpublished - rights reserved under the Copyright laws of the // United States. // //============================================================================= #include <stdio.h> #include <stdlib.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #include <winioctl.h> #include \"common.h\" // This is a simple console app that exercises the interrupt demo // driver. // // The test app waits for the driver to notify it that there is // interrupt data to read. The driver notifies the app by setting // an event whose handle the app passes to the driver at startup. // The app simply emits the interrupt data (a count and a timestamp) // to the console. TIMESTAMP tsbuf[FIFOSIZE]; HANDLE h, hEvent; ///////////////////////////////////////////////////////////////// // ServiceThread // // This thread is awakened by the driver to tell the app to come // and get the interrupt records // DWORD WINAPI ServiceThread(PVOID hEvent) { ULONG nItems, nBytesRead; PTIMESTAMP pts; while (TRUE) { WaitForSingleObject(hEvent, INFINITE); printf(\"New event:\\n\"); if (!DeviceIoControl( h, IOCTL_GET_TIMESTAMP_DATA, NULL, 0, tsbuf, sizeof(tsbuf), &nBytesRead, NULL) ) { printf(\"DeviceIoControl failed %x\\n\", GetLastError()); exit(1); } nItems = nBytesRead/sizeof(TIMESTAMP); for (pts = tsbuf; nItems; nItems--, pts++) printf(\"Interrupt time %08x (High=%08x) count %x\\n\", pts->ts_time, pts->ts_interrupt_count); } return 0; } ///////////////////////////////////////////////////////////////// // // Main // void __cdecl main(int ac, char* av[]) { DWORD Tid; ULONG error; ULONG nRet; // Open the device h = CreateFile(\"\\\\\\\\.\\\\IntrDemo0\", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) { error=GetLastError(); fprintf(stderr, \"Cannot open device, error %d (0x%x)\\n\", error, error); exit(1); } // Create an event for notification hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (! DeviceIoControl( h, IOCTL_SET_NOTIFICATION_EVENT, &hEvent, sizeof(hEvent), NULL, 0, &nRet, NULL ) ) { printf(\"Ioctl failed: %x\\n\", GetLastError()); exit(1); } // Create the thread that waits for the event CreateThread(0, 0x1000, ServiceThread, (PVOID)hEvent, 0, &Tid); printf(\"press return to exit . . .\\n\"); // Look for a key to terminate while (TRUE) if (_getche() == 0xd) break; CloseHandle(hEvent); CloseHandle(h); } |
|
|
板凳#
发布于:2003-07-29 18:06
2、在驱动中这样处理:
////////////////////////////////////////////////////////////////// // DeviceControl // // The test app uses a DeviceIoControl call for two purposes: // // 1. It passes an event handle to the driver. The driver sets // the event when there is something for the app to do, i.e., // when an interrupt occurs, and the app fetches the data. // // 2. It fetches the timestamp data for the interrupts. // NTSTATUS InterruptDemoDevice::DeviceControl(KIrp I) { T << I; I.Information() = 0; switch (I.IoctlCode()) {//注意这里 case IOCTL_SET_NOTIFICATION_EVENT: { HANDLE hEvent = *(HANDLE*)I.IoctlBuffer(); if (m_pEvent) delete m_pEvent; m_pEvent = new (NonPagedPool) KEvent(hEvent, OBJECT_TYPE_ALL_ACCESS); return I.Complete(STATUS_SUCCESS); } case IOCTL_GET_TIMESTAMP_DATA: if (SynchronizeInterrupt(&m_Interrupt, LinkTo(ReadTimeFifo), PIRP(I)) ) return I.Complete(STATUS_SUCCESS); else return I.Complete(STATUS_UNSUCCESSFUL); break; default: T << \"Bad Request: \" << I.IoctlCode() << \"\\n\"; return I.Complete(STATUS_INVALID_PARAMETER); } } ////////////////////////////////////////////////////////////////// // Isr // // This is the interrupt service routine. Since we always return // FALSE (to indicate that we did not service the interrupt), there // is no interaction with the hardware required. The system will // call the actual floppy interrupt handler. This routine justs // counts the interrupt (m_InterruptCount), grabs a timestamp, // and requests queues the DPC object. // BOOLEAN InterruptDemoDevice::Isr(void) { T << \"In the ISR\\n\"; TIMESTAMP ts; ts.ts_interrupt_count = ++m_InterruptCount; KeQueryTickCount(&ts.ts_time); m_TimeStampFifo.Write(&ts, 1); m_Dpc.Request(); return FALSE; } ////////////////////////////////////////////////////////////////// // Dpc // // This the callback associated with the device\'s DPC object. The // ISR queues the dpc object, resulting in a call to this routine. // It invokes the synch crit section member function TestAndClearNotifyApp, // which determines if it is necessary to notify the app of the // interrupt. The idea is that we only notify the app when there // is no outstanding interrupt to which the app has not responded. // VOID InterruptDemoDevice::Dpc(PVOID Arg1, PVOID Arg2) { BOOLEAN Notify; BOOLEAN SynchStatus; if (m_pEvent) { SynchStatus = SynchronizeInterrupt( &m_Interrupt, LinkTo(TestAndClearNotifyApp), &Notify ); if (SynchStatus) { T << \"DPC, App notify=\" << ULONG(Notify) << \"\\n\"; if (Notify) //注意这里 m_pEvent->Set(); } else T << \"Dpc error synchronizing\\n\"; } } |
|
|
地板#
发布于:2003-07-31 10:53
谢谢Dragon大虾!!!
送分了!!!! 已经改写了,但是每次运行到延迟中断里面的 KEvent->Set()的时候就蓝屏死机了,请问是什么回事啊? [编辑 - 7/31/03 by lamxu] |
|
地下室#
发布于:2003-07-31 14:24
set前最好先判断一下该事件是否有效,如下所示:
if(IntEvent!= NULL) IntEvent->Set(IO_NO_INCREMENT,FALSE); |
|
|