驱动事件对象

事件对象

驱动程序可以使用一个事件对象挂起当前线程等待直到底下一层驱动程序处理一个等待者驱动程序建立的IRP。 拥有驱动创建的线程的驱动程序,或者在一个同步IO请求的completion例程上等待的驱动派遣例程同样可以使用一个事件对象在他们的线程和(或)其他驱动例程之间同步操作。

这一章包含以下主题:

定义和使用一个事件对象

标准事件对象


定义和使用一个事件对象

任何使用一个事件对象的驱动程序在它等待,设置,清除或者重置一个事件对象之前必须调用KeInitializeEventIoCreateNotificationEvent或者IoCreateSynchronizationEvent

下图说明了一个线程内的驱动程序如何使用一个事件对象作同步操作。

 

如上图所示,驱动程序必须提供事件对象的非分页的存储空间。 The driver can use the device extension of a driver-created device object, the controller extension if it uses acontroller object, or nonpaged pool allocated by the driver.

当驱动调用KeInitializeEvent,它必须传递一个指向存储事件对象的非分页内存指针。另外调用者必须制定事件的初始状态(信号态或者非信号态)。调用者同样必须指定事件的类型,类型可以为以下之一:

· 

SynchronizationEvent

· 

当一个SynchronizationEvent 的事件被设置为信号态,在其上等待信号转变为非信号态的一个线程被操作系统设置为准备好执行状态(取消阻塞),而且事件的状态被自动重设为非信号态。这种类型的事件有时候被叫做自动清除事件,因为它的信号态状态在每次等待完成后被自动重设。

·  

NotificationEvent

· 

当一个NotificationEvent的事件被设置为信号态所有在此事件上等待的线程都被操作系统设为准备好执行。并且事件依然保持信号态直到显式地重设为非信号态:也就是以此事件对象为参数调用了KeClearEvent或者KeResetEvent

· 

少数的设备或者中间层驱动程序拥有一个驱动专用的线程,还有一些线程可能需要通过等待事件同步它们的操作保护一个共享的资源。

大部分使用事件对象等待IO操作完成的驱动程序调用KeInitializeEvent时设置参数TypeNotificationEvent

驱动程序通过IoBuildSynchronousFsdRequest或者IoBuildDeviceIoControlRequestIRP创建的事件对象几乎总是设置为NotificationEvent,因为调用者将等待一个或者多个底层驱动程序已经满足了它的请求的事件通知。

在驱动程序初始化完自身之后,它的驱动专用的线程(如果存在的话),和其他的例程可以通过这个事件同步它们的操作。例如,驱动程序拥有一个管理IRP排队的线程,例如系统软盘控制器驱动,可能需要在这个事件上同步IRP处理,如前图所示:

1. 

线程从处理设备访问的IRP队列中取出一个IRP,调用KeWaitForSingleObject以一个指向驱动提供的内存作为参数初始化事件对象。

2. 

其他驱动例程执行满足这个IRP的必要设备IO操作,当这些操作完成后,驱动程序的DpcForIsr例程以这个事件对象的指针为参数调用KeSetEvent,提高这个线程的驱动相关的优先级(增加,如上图所示),并且调用KeSetEvent,它的Boolean类型参数Wait设置为FALSE。等待事件对象变为信号态,从而将等待线程变为ready状态。

3. 

当一个处理器可用时,内核调度这个线程执行:这个可用条件也就是,在ready态的线程中没有其他比这个线程具有更高优先级,并且在更高级的IRQLS上没有其他驱动模式例程需要执行时。

4. 

调用KeSetEvent时设置Wait参数为TRUE意味着调用者试图在KeSetEvent返回后直接调用一个KeWaitForSingleObject或者KeWaitForMultipleObjects支持例程。

考虑以下KeSetEvent设置Wait参数的准则:

一个运行在IRQL<DISPATCH_LEVEL上可分页的线程或者一个可分页的驱动例程,不应当以Wait参数TRUE调用KeSetEvent。如果调用者在使用KeSetEvent之后,在KeWaitForSingleObject或者KeWaitForMultipleObjects之前的时候恰巧被交换出物理内存,那么将导致一个严重的页面错误。

任何运行在IRQL = DISPATCH_LEVEL的标准驱动例程不能在尚未降下系统(without bringing down the system)时在调度对象上等待非0的时间。然而像这样的例程可以在IRQL<=DISPATCH_LEVEL时调用KeSetEvent

有关标准驱动程序例程运行时的IRQL总结,见Managing Hardware Priorities

KeResetEvent 返回给定事件的前一个状态:不管toKeResetEvent调用时事件是信号态还是非信号态。KeClearEvent简单地设置给定的时间为非信号态。

在调用前述的例程时考虑以下准则:

为提供更好的性能,每一个驱动程序应当调用KeClearEvent除非调用者需要使用KeResetEvent返回的信息去决定下一步该做什么。

 


标准事件对象

操作系统提供了一些标准事件对象。当特定条件满足时,驱动程序可以使用这些事件对象去获得通知。以下列表包含了这些标准事件对象:

\KernelObjects\HighMemoryCondition

This event is set whenever the amount of free physical memory exceeds a system-defined amount. Drivers can wait for this event to be set as a signal to aggressively allocate memory.

\KernelObjects\LowMemoryCondition

This event is set whenever the amount of free physical memory falls below a system-defined amount. Drivers that have allocated large amounts of memory can wait for this event to be set as a signal to free unused memory.

For Microsoft Windows Server 2003 and later versions of Windows, drivers can also use the following additional standard event objects:

\KernelObjects\HighPagedPoolCondition

This event is set whenever the amount of free paged pool exceeds a system-defined amount. Drivers can wait for this event to be set as a signal to aggressively allocate memory from paged pool.

\KernelObjects\LowPagedPoolCondition

This event is set whenever the amount of free paged pool falls below a system-defined amount. Drivers that have allocated large amounts of memory can wait for this event to be set as a signal to free unused memory from paged pool.

\KernelObjects\HighNonPagedPoolCondition

This event is set whenever the amount of free nonpaged pool exceeds a system-defined amount. Drivers can wait for this event to be set as a signal to aggressively allocate memory from nonpaged pool.

\KernelObjects\LowNonPagedPoolCondition

This event is set whenever the amount of free nonpaged pool falls below a system-defined amount. Drivers that have allocated large amounts of memory can wait for this event to be set as a signal to free unused memory from nonpaged pool.

For Windows Vista and later versions of Windows, drivers can also use the following additional standard event objects:

\KernelObjects\LowCommitCondition

This event is set when the operating system's commit charge is low, relative to the current commit limit. In other words, memory usage is low and a lot of space is available in physical memory or paging files.

\KernelObjects\HighCommitCondition

This event is set when the operating system's commit charge is high, relative to the current commit limit. In other words, memory usage is high and very little space is available in physical memory or paging files, but the operating system might be able to increase the size of its paging files.

\KernelObjects\MaximumCommitCondition

This event is set when the operating system's commit charge is near the maximum commit limit. In other words, memory usage is very high, very little space is available in physical memory or paging files, and the operating system cannot increase the size of its paging files. (A system administrator can always increase the size or number of paging files, without restarting the computer, if sufficient storage resources exist.)

Each of these events are notification events. They remain set as long as the triggering condition remains true.

想要打开这些对象中的任何一个句柄,使用 IoCreateNotificationEvent 例程。想要等待任意一个其中事件的驱动程序应当创建一个专用线程去等待这些事件。线程可以调用KeWaitForSingleObject 或者KeWaitForMultipleObjects等待其中一个或者多个事件。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值