lamxu
驱动牛犊
驱动牛犊
  • 注册日期2003-04-11
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1726回复:4

驱动程序如何发消息给应用程序?

楼主#
更多 发布于:2003-07-29 16:34
我想利用事件实现驱动程序向应用程序发消息。

我设想在DeviceIocontrol里面分配事件,在延迟中断里设置事件。

这样可行吗?应用程序如何设计去配合?有例子源码吗?

送分!送分!

最新喜欢:

yuanyuanyuanyu...
Dragon2008
驱动中牛
驱动中牛
  • 注册日期2002-04-01
  • 最后登录2006-03-13
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望5点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于: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);
}
我姓龙,我属龙,我叫龙。。。
Dragon2008
驱动中牛
驱动中牛
  • 注册日期2002-04-01
  • 最后登录2006-03-13
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望5点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于: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\";
}
}
我姓龙,我属龙,我叫龙。。。
lamxu
驱动牛犊
驱动牛犊
  • 注册日期2003-04-11
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-07-31 10:53
谢谢Dragon大虾!!!
送分了!!!!

已经改写了,但是每次运行到延迟中断里面的 KEvent->Set()的时候就蓝屏死机了,请问是什么回事啊?

[编辑 -  7/31/03 by  lamxu]
Dragon2008
驱动中牛
驱动中牛
  • 注册日期2002-04-01
  • 最后登录2006-03-13
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望5点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-07-31 14:24
set前最好先判断一下该事件是否有效,如下所示:
if(IntEvent!= NULL)
IntEvent->Set(IO_NO_INCREMENT,FALSE);
我姓龙,我属龙,我叫龙。。。
游客

返回顶部