阅读:1836回复:16
jim_little老大,关于driverworks中的kevent对象使用的问题,头都大了!!
要在设备类中使用kevent对象,应该在哪里声明,在哪里实例化?
我总是出现页错误。我应该怎么做啊? 好像是申请内存时出问题。 [编辑 - 6/14/02 by brucezh] |
|
|
沙发#
发布于:2002-06-17 17:35
在类的头文件中声明,Kevent m_event;
看一下例子。 ADevice::ADevice(ADevice* previous, ULONG Unit) : // Base class KDevice( KUnitizedName(L\"A\", Unit), FILE_DEVICE_UNKNOWN, KUnitizedName(L\"A\", Unit), 0, DO_DIRECT_IO ), // KPciConfiguation m_Cfg(VENDOR_ID, DEVICE_ID, previous ? &previous->m_Cfg : NULL), m_event(NotificationEvent), ...... { ...... } 另外,我也是刚开发完一个项目,粗懂而已,平常我从不到这里来,想不到今天来到这,还有专门找我的,受丛若惊! [编辑 - 6/17/02 by Jim_little] |
|
|
板凳#
发布于:2002-06-18 10:39
我也是这么做的,可是总是系统崩溃。
是不是2000下不支持使用事件进行同步的处理呢?好像walt oney的书上提到,在2000下,应用程序和驱动程序的同步,标准办法是发送ioctl,驱动返回ntstatus_pending,当事件发生时完成irp。 你在项目中使用事件进行同步了没有?是在98还是2000下呢? 多谢。 |
|
|
地板#
发布于:2002-06-18 10:48
2000下和98下都支持事件同步呀,我的都成功了。
你的系统是在等待事件的时候崩溃的吗?我记得等待事件 这条指令必须运行在dispatch level以下,如果在中断中使用 系统就会崩溃。你可以查一查。 |
|
|
地下室#
发布于:2002-06-18 11:05
#define DRIVER_EVENT_NAME L\"\\\\BaseNamedObjects\\\\SynchEvent\"
在设备类中定义了 KEvent* m_pSynchEvent, 在设备类构造函数中: m_pSynchEvent = new (NonPagedPool) KEvent( KUstring(DRIVER_EVENT_NAME),SynchronizationEvent); m_pSynchEvent->Clear(); 然后一加载就死机,不知道怎么回事。 如果可以,能不能把你的详细做法告诉我?只是关于事件同步的,不胜感激 |
|
|
5楼#
发布于:2002-06-18 11:24
我的应用很简单,就是wait,set,reset.初始化就象我说的那样。
不过我创建的是无名事件,NotificationEvents 类型的。和你的不一样,你这种有名事件我没有用过。 我建议: 1、先把事件创建出来,然后所有其它有关此事件的操作全部屏蔽,看看是否死机。如果不死机,说明是在使用事件的过程中造成死机。 2、换换事件类型,改为手动NotificationEvents。 2、如果仍然死机,换成无名事件试一试。 一般死机的原因就是某个语句不合适造成的。 |
|
|
6楼#
发布于:2002-06-18 11:28
多谢,我会试的。
不过,用无名事件怎样实现同步功能呢? 也就是说,这个事件句柄怎样传给应用程序呢,是不是在IOCTL函数中把事件句柄传过去? |
|
|
7楼#
发布于:2002-06-18 11:31
另外,应用程序要知道事件的状态,是用查询吗?肯定不能用WAITFORSINGLEOBJECT()了
|
|
|
8楼#
发布于:2002-06-18 11:55
ZDCat的回答:
“ 最简单的方式是在应用层创建事件(event),将事件句柄传给驱动,然后中断服务后,在dpc例程中讲事件设置为信号态。同时应用层另开一个线程监视这个事件,如果发生则表明中断发生。 ” 这种方法你试一试。如果要支持多进程,则创建有名事件,否则,创建无名事件就足够了。 你可以搜索一下ABC初学者相关帖子,这方面例子很多。 我没有具体作过,你还要自己摸索。 |
|
|
9楼#
发布于:2002-06-18 12:00
这样在应用程序中就可以调用waitforsigleobject了。
其实我觉得只要应用程序知道了事件的句柄,即使事件是在驱动程序中创建的,也应该可以用waitforsigleobject。因为句柄在系统中是唯一的。 你说的“另外,应用程序要知道事件的状态,是用查询吗?肯定不能用WAITFORSINGLEOBJECT()了”不知丛何得知,望指教。这些我都没有作过。 |
|
|
10楼#
发布于:2002-06-18 12:04
Driverworks的帮助,供参考!
How to Signal an Application from a Kernel Mode Driver Sometimes a driver needs to signal an application. There are at least three ways to do this: Method 1 The application makes a DeviceIoControl to the driver. The driver returns STATUS_PENDING. When the event occurs, the driver completes the IRP. The thread returns from the DeviceIoControl call and handles the event. // sample class declaration class MyDevice : public KDevice { public: MyDevice(); VOID EventHandler(void); DEVMEMBER_DISPATCHERS DEVMEMBER_CANCELIRP (MyDevice, CancelSignalIrp); KIrp m_IrpToCompleteToSignalEvent; }; // Handler for Device Control requests NTSTATUS MyDevice::DeviceControl(KIrp I) { switch (I.IoctlCode()) { case MYDEVICE_IOCTL_SETUP_SIGNAL: CancelSpinLock::Acquire(); I.SetCancelRoutine(LinkTo(CancelSignalIrp)); m_IrpToCompleteToSignalEvent = I; CancelSpinLock::Release(); return STATUS_PENDING; break; . . . } } // cancel routine for the signal IRP VOID MyDevice::CancelSignalIrp(KIrp I) { m_IrpToCompleteToSignalEvent = KIrp(NULL); I.Information() = 0; CancelSpinLock::Release(I->CancelIrql); I.Complete(STATUS_CANCELLED); } // Routine that completes the IRP to signal the event // to the application. Not callable at IRQL > DISPATCH_LEVEL. VOID MyDevice::EventHandler(void) { KIrp I = m_IrpToCompleteToSignalEvent; m_IrpToCompleteToSignalEvent = KIrp(NULL); I.Information() = 0; I.Complete(STATUS_SUCCESS); } Method 2 The application creates an event object, and passes the handle to the driver via DeviceIoControl. The driver obtains an object pointer for the event, which it can then set or reset. Note that the thread handle is specific to the calling process. Therefore, this method can only be used for monolithic or highest level drivers. // sample class declaration class MyDevice : public KDevice { public: MyDevice(); VOID EventHandler(void); KEvent * m_pEventToSignal; }; // Handler for Device Control requests NTSTATUS MyDevice::DeviceControl(KIrp I) { switch (I.IoctlCode()) { case MYDEVICE_IOCTL_SETUP_SIGNAL: // app passes event handle in input buffer HANDLE hEvent = *(HANDLE*)I.IoctlBuffer(); m_pEventToSignal = new(NonPagedPool) KEvent(hEvent); NTSTATUS status = (m_pEventToSignal != NULL) : STATUS_SUCCESS ? STATUS_INSUFFICIENT_RESOURCES; return I.Complete(status); break; . . . } } // Routine signals the event to the application. // Not callable at IRQL > DISPATCH_LEVEL. VOID MyDevice::EventHandler(void) { m_pEventToSignal->Set(); // or Pulse } Method 3 (Not available in versions of Windows NT earlier than 4.0.) Create a named event. #define APP_EVENT_NAME \"SynchEvent\" #define DRIVER_EVENT_NAME L\"\\\\BaseNamedObjects\\\\SynchEvent\" // Application code hEvent = OpenEvent(SYNCHRONIZE, FALSE, EVENT_NAME); // The driver must have already created the event in // order for this to succeed. If you want the app to // create the event, use CreateEvent instead of OpenEvent. // If the user is not privileged, it is required to // create the event in the application. // Driver Initialization Code KEvent* m_pSynchEvent = new (NonPagedPool) KEvent( KUstring(DRIVER_EVENT_NAME),SynchronizationEvent); m_pSynchEvent->Clear(); // initially signaled // The following code signals the event m_pSynchEvent->Set(); |
|
|
11楼#
发布于:2002-06-18 12:10
ZDCat的回答: 呵呵,谢谢署我的名,不过应该是zydcat 创建事件在应用层和内核都可以,我一般是这样做的,在内核创建事件,在应用层只要等待同名事件发生就可以了,反正创建的事件名称你知道,在哪儿等都可以。当然的开个线程了。 |
|
|
12楼#
发布于:2002-06-18 12:18
方法3好象就是你用的方法.
To zydcat: sorry!我记错了,谁叫你的名字很难记。直接叫cat多好! |
|
|
13楼#
发布于:2002-06-18 12:44
To zydcat: 唉,我也不想呀,cat太多了,再说一点也没有个性。前面是我姓名的缩写 |
|
|
14楼#
发布于:2002-06-18 12:51
让我猜一猜:
张亚东?right? |
|
|
15楼#
发布于:2002-06-18 12:53
拜托,虽然不对
但也不要这么大声,让别人都听到了 |
|
|
16楼#
发布于:2002-06-18 12:58
怕是被我猜中了,心虚了吧?
|
|
|