windows内核开发笔记十:PAGED_CODE在驱动开发中的作用

windows内核开发笔记十:PAGED_CODE在驱动开发中的作用

#if DBG
#define PAGED_CODE() \
    if (VideoPortGetCurrentIrql() > 1 /*APC_LEVEL*/) { \
        VideoPortDebugPrint(0, "Video: Pageable code called at IRQL %d\n", VideoPortGetCurrentIrql() ); \
        ASSERT(FALSE); \
        }

#else
#define PAGED_CODE()
#endif

功能:此宏可以确保调用线程运行在一个允许分页的足够低IRQL级别。

参数: 无参数

返回值: 无

注意:
如果IRQL > APC_LEVEL,则PAGED_CODE()会对系统产生一个断言。

  1. 这个宏的调用必须在驱动程序开始位置,并且包含可分页代码或者可访问分页代码
  2. 这个宏定义只在驱动代码执行宏时检查IRQL,如果此宏之后提高 IRQL等级 ,将无法检测改变。
  3. 必须使用其它 Static Driver Verifier 和Driver Verifier去检测等级,当IRQL在不适当的时候被提升 
  4. 此宏定义只在checked builds.版本中运行
     

   也就是说,Windows并没有将运行在Ring 0的代码全部视为内核,而是区分为Kernel和Executive,Executive可以理解为“管理层”的意思,解释为“执行体”不合理。

   其中,Kernel是狭义的内核,里面的代码包括用到的数据,都是常驻在物理内存中的,不支持分页机制。

   而除此之外的代码和数据,是支持分页机制的,并且可以被交换到pagefile中,即并非总是在物理内存中的。

 

   对于驱动来说,应该属于后者,因此在驱动中的函数的头部都会使用PAGED_CODE来判断一下,

   #define PAGED_CODE() PAGED_ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

#define PASSIVE_LEVEL 0 // Passive release level

#define LOW_LEVEL 0 // Lowest interrupt level

#define APC_LEVEL 1 // APC interrupt level

#define DISPATCH_LEVEL 2 // Dispatcher level

#define CMCI_LEVEL 5 // CMCI handler level

 
#define PROFILE_LEVEL 27 // timer used for profiling.

#define CLOCK1_LEVEL 28 // Interval clock 1 level - Not used on x86

#define CLOCK2_LEVEL 28 // Interval clock 2 level

#define IPI_LEVEL 29 // Interprocessor interrupt level

#define POWER_LEVEL 30 // Power failure level

#define HIGH_LEVEL 31 // Highest interrupt level

 
#define CLOCK_LEVEL (CLOCK2_LEVEL)

如果当前的中断请求级别(IRQL)太高(DPC以上),那么很可能属于Kernel部分,因此在使用时,要加以规避和避免。
 

 

你可能感兴趣的:(操作系统,windows内核,系统内核,内核,驱动编程,操作系统,VC,windows编程)