欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

【翻译】winddk翻译(七)--多处理器安全

【翻译】winddk翻译(七)--多处理器安全

Kernel-Mode Driver Architecture: Windows DDK
多处理器安全
基于NT的操作系统被设计成可以运行于单处理器或者对称多处理器(symmetric multiprocessor[SMP])平台上,同样内核驱动程序也应该如此。
在所有Microsoft Windows多处理器平台上, 都存在以下的条件: 
所有的CPU都是一样的,没有任何CPU能够拥有一样的协处理器。
所有的CPU分享一块内存并且拥有一致的访问内存的权力。
在对称(symmetric)多平台上,每一个CPU都能够访问内存,处理中断,以及访问I/O控制寄存器。(相反地,在一个非对称(asymmetric)多处理器机器在上,一个CPU处理所有其他CPU的中断)。

为了多处理器平台下的运行安全,一个操作系统必须得保证运行于单处理器的代码一不会同时访问和修改另一个处理正在访问和修改的数据。例如,如果一个最低层的驱动的ISR只在一个处理器上处理一个设备的中断,她就必须独享这个设备寄存器或者驱动定义的数据,以防止同时发生在另一处理器上的设备中断。
更重要的是,一个在单处理器机器上能够处理的驱动的连续I/O操作可能在对称多处理器电脑上发生重叠。也就是说,一个驱动的处理输入I/O请求例程 可能正在一个处理器上执行,但是另一个与设备通信的例程更在另一个处理器上执行。无论内核模式驱动是在单处理器上或者是对称多处理器上执行,她们都必须得对所有驱动定义的数据和系统提供的在不同驱动例程当中共享的资源进行同步,当然也得同步对特理设备的访问,如果存在物理设备的话。
NT内核组件提供一种称为自旋锁的同步机制。驱动程序能够使用这种机制保护在对称多处理器平台上同时运行的一个或者多个例程共享的数据(或者设备寄存器)免受多个例程的同时访问。内核强制两种使用自旋锁的规则:
一个例程可以在任何时候拥有一个特定的自旋锁。在访问共享数据,每一个例程必须访问该共享数据的例程必须得首先申请该数据的自旋锁。为了访问同一段数据,另一个例程只有申请得到自旋锁才可以访问,但是自旋锁在之前那个例程没有释放之前是不可能申请得到的。
内核为系统当中的每一个自旋锁都绑定了一个IRQL值。只有当一个内核模式的例程运行于自旋锁的IRQL时,才能够申请得到该自旋锁。
这两个规则防止一个运行于低层IRQL驱动的例程,但持有一个自旋锁的被线程被基其他拥有高优先级的驱动例程得到。以防止死锁的发生。
绑定到自旋锁上的IRQL一般情况是申请自旋锁的拥有最高IRQL的例程的IRQL。
例如,一个最底层驱动的ISR常常与这个驱动的DPC例程共享一些状态数据。这个DPC例程调用一个驱动提供的临界区(critical section)例程去访问共享数据。 保护共享数据的自旋锁拥有和设备中断DIRQL 一样的IRQL。只要临界区例程保持一个自旋锁然而以DIRQL级别来访问共享数据,这个ISR就不能够运行任何的单处理器或者对称多处理器电脑上了。 
这个ISR不能够运行于单处理器机器是因为这个设备中断已经被屏蔽了,见总是可优先和总是可中断
在一个对称多处理器的机器上,一个ISR在临界区例程保持一个自旋锁并且在DIRQL访问共享数据时,不能够得到保护共享数据自旋锁。
一系列的内核模式线程能够同步共享数据或者一些被其他内核的分派对象:事件(event),互斥体(mutex),信号(semaphore),时钟(timer)或者基他线程访问。然而,大部分的驱动不会创建其自身的线程,因为如果避免线程上下文切换的话,能够得到更好的效率。当一个时间-严重的内核模式支持例程和驱动运行于IRQL=DISPATCH_LEVEL或者在DIRQL时,她们必须使用内核的自旋锁来同步共享数据或者资源的访问。
更多信息,见自旋锁,管理硬件优先级 和 内核分派对象。

Microsoft Corporation
Send feedback on this topic
Built on Friday, February 18, 2005

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功