注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

写着玩

Bob

 
 
 

日志

 
 
 
 

陷阱调度--3  

2009-07-26 23:55:49|  分类: Win32 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

http://hi.baidu.com/l_wait/blog/item/5c22133357b7c5fc1b4cff5e.html

软件中断请求级别(Software Interrupt Request Levels ,IRQLs)

       虽然中断控制器做了中断级别的优化工作,Windows还是强制性地使用了自己的中断优先级方案,即IRQLs。内核在内部以数字表示IRQLs,x86上是从 0到31,x64和IA64上是从0到15,数字越高则中断的优先级别越高。内核为软件中断定义了一系列标准的IRQLs,HAL也将硬件中断号映射到 IRQLs。

如图 interrupt request levels (IRQLs)

陷阱调度--3 - yolcy - 写着玩

      中断是根据优先级被响应的,一个高优先级的中断会比一个低优先级的中断先被响应。当有一个高优先级的中断产生,处理器保存被中断线程的状态并呼叫与之相关的陷阱调度器(trap dispatchers)。陷阱调度器提升IRQL并调用该中断的服务例程。在中断例程结束之后,陷阱调度器降低处理器的IRQL到中断发生前的级别,接着载入之前存储的机器状态。被中断的线程从被中断的点重新开始执行。当内核降低IRQL之后,之前被屏蔽的优先级较低的中断就可能被接收。如果顺利的话,内核会重复这一过程来处理新的中断。

      IRQL的优先级与线程调度的优先级完全不同。后者是线程的一个属性,而IRQL是中断源,比如键盘、鼠标的一个属性。此外,每个处理器有一个IRQL设置,该设置在执行系统代码时发生变化。

      每个处理器的IRQL设置决定了该处理器可接收的中断。IRQLs也被用来同步访问内核模式的数据结构。当一个线程在内核模式下运行,它既可以直接调用 KeRaiseIrql和KeLowerIrql来提升或降低处理器的IRQL,也可以间接地通过调用函数获得内核同步物件以提升或降低处理器的 IRQL。从拥有高于当前IRQL的中断源发出的中断可以中断处理器,而从有着小于或等于当前IRQL的中断源发出的中断会被屏蔽,直到有执行线程降低该 IRQL。

      访问PIC是一个相对费时的操作,于是使用PIC的HALs做了个性能优化,叫做lazy IRQL,来避免PIC访问。如果IRQL被提升,HAL将内部记录这个新的IRQL而不去改变中断掩码。如果接下来有一个低优先级的中断发生,HAL就设置中断掩码以适应第一个中断并且推迟低优先级的中断直至IRQL被降低。因此,如果在IRQL升高时没有低优先级的中断发生,HAL就不必修改PIC。

    一个内核模式的线程提升或降低运行它的处理器的IRQL取决于它的任务。例如,如果一个中断发生,陷阱处理程序(或者是处理器)会提升处理器的IRQL到该中断源指定的IRQL。这个高度屏蔽了所有小于或等于该IRQL的中断(只作用于该处理器),保证了在处理器响应该中断的过程中不会被同级或级别较低的中断打断。被屏蔽的中断要么被交由其它的处理器处理,要么就要等到IRQL降下来。因此,系统中的所有组件,包括内核和设备驱动都希望IRQL能够待在无源级别(也叫作低级别)。原因是如果IRQL不被长时间的置于较高的状态,设备驱动就可以及时地响应硬件中断。

//EXPERIMENT: Viewing the IRQL

      由于改变处理器的IRQL对操作系统影响较大,所以这种改变只允许在内核模式下进行——用户模式的线程不能改变处理器的IRQL。这也意味着如果处理器正运行一个用户模式的代码,那么处理器的IRQL将处于无源级别。只有处理器执行内核模式代码时IRQL会升高。

    每个中断级别都有其专门用途。例如,内核发出一个处理器间中断(Inter-processor interrupt,IPI)以要求另一个处理器去完成某个动作,像是调度某个线程或者更新它的转换后备缓冲器(TLB)的高速缓存。系统时钟定时产生一个中断,内核响应该中断:更新系统时间并且测量线程执行的时间。如果硬件平台支持两个时钟,内核就添加另一个时钟中断级别以测量性能。HAL提供多个中断级别供中断控制设备使用;具体的数量随处理器和系统配置而不同。内核使用软件中断来启动线程或异步地停止线程的执行。

   

映射中断到IRQLs

    IRQL级别不同于中断控制器定义的IRQs——Windows的体系结构中没有在硬件中实现IRQLs这个概念。那么Windows是怎么给一个中断指派IRQL的呢?答案要问HAL。在Windows中,有一种叫做总线驱动的设备驱动,它决定了在其总线(PIC、USB等等)上出现的设备和为该设备分配的中断。总线驱动向即插即用管理器报告此信息,管理器在考虑了要配给其它设备的中断后决定分配给每个设备的中断。接着它调用HAL函数HalpGetSystemInterruptVector,该函数映射这些中断到IRQLs。

    分配算法是随Windows包含的HALs不同而不同。在单处理器x86系统中,HAL完成了一个直译:一个给定的设备的IRQL的计算方法为27减去其中断向量。因此,如果一个设备的中断向量是5,它的ISR在IRQL为22时执行。在一个x86多处理器系统中,映射就不是这样简单了。APICs支持超过200个中断向量,所以没有足够的IRQLs以一一对应。因此,多处理器HAL以轮转的方式给中断向量分配IRQLs,在设备IRQL范围中循环。结果是,在一个x86多处理器系统中无法预知Windows赋予APIC IRQs的IRQL是什么。最后,在x64和IA64系统中,HAL计算给定IRQ的IRQL的方法是用分配给IRQ的中断向量除以16。

预定义的IRQLs

    让我们近距离观察预定义的IRQLs,从最高级别开始:

~内核只在用KeBugCheckEx停止系统并屏蔽所有中断时使用High级别 。

~Power fail级别源自Microsoft Windows NT设计文档,它指出系统电源故障码的行为,但是这个IRQL未被使用。

~级别是用来让另一个处理器去完成某个动作,像是列入一个DISPATCH级别的中断以调度某个特定线程执行,更新处理器的转换后备缓冲器(TLB)的高速缓存,系统关闭,或者系统崩溃。

~Clock级别供系统时钟使用,内核用它获取时间同时测量并分配CPU时间给线程。

~系统的实时时钟在内核概要分析(kernel profiling,一种性能测试机制)启用时会用到profile级别。当内核概要分析被激活,内核的概要分析陷阱处理程序会在中断发生时记录下当下执行代码的停止位置。之后会构建一个地址采样表,使工具可以从中提取并分析数据。

你可以下载Kernrate,它是一个内核概要分析工具。

device IRQLs用以按优先级排列中断。

DPC/dispatch级别和APC级别是内核及设备驱动产生的软件中断。

lowestIRQL,无源级别,并非真正的中断级别;它实际是使一般线程能够运行且允许任何中断触发的一种设置。

//EXPERIMENT: Using Kernel Profiler to Profile Execution

       对于运行于DPC/dispatch或更高级别的代码来说有一个重要的限制,它不能一直等待某个物件直到需要调动程序选择另一个线程来执行,这是一个非法操作,因为调度程序将它的数据结构同步到了DPC/dispatch级别,因此无法被调用来重新调度。另一个限制是只有未分页内存可以在DPC/dispatch以及更高级别被访问。这个规则实际上是前一个限制的副作用,因为尝试访问一个不在内存中的页会导致缺页错误。如果发生了一个缺页错误,内存管理器就会启动一个磁盘I/O,然后就等待文件系统驱动从磁盘读如该页。这一等可能就会让调度程序做一次上下文切换(如果此时没有用户线程排队,就切换到空闲线程),这样一来就违背了调度程序在此情况下不能被调用的规则(因为IRQL在读磁盘的时候仍然处于DPC/dispatch或更高级别)。如果违反了前述两个限制中的任意一个,系统就会崩溃,崩溃代码是IRQL_NOT_LESS_OR_EQUAL。是

  评论这张
 
阅读(475)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017