1. DDK中的"When Should Code and Data be Pageable?"一节里提到

(1)如果某段驱动代码做了“访问分页内存”、“调用了其他放在分页内存中的例程”、“访问了用户线程环境中的内存(我理解为R3级进程中的内存)”这些事情中的任意一件或多件,则该段代码"must be"放到分页内存。
         这句话其实很好理解:把代码段放到分页内存无非也是为了节约核心内存,可是为什么MS会强调“must be”呢?以我恶毒的心灵,仍然没能揣测出来~
(2)如果某段驱动代码满足以下任意一个或多个要求,则它 “cannot be ”被分页。
         “运行IRQL = DISPATCH_LEVEL ”、“申请了Spin锁”、“以参数‘Wait=TRUE’,调用了管理内核对象的函数,"。
         对于第三种情况,DDK上是这么说的:                
         “Wait参数为TRUE,则该函数返回时IRQL是DISPATCH_LEVEL,而且调度函数数据库会被锁定(原话为‘the dispatcher database locked’,我理解为所有的IRP_MJ_XXX的响应函数都被锁定,不知道这么理解对不对~)”
   总结一句,如果该段代码本身就运行在DISPATCH_LEVEL、或者访问了DISPATCH_LEVEL上的内存,则不能被分页。

 

  2.#pragma alloc_text(PAGEXxxx, RoutineName)
      上面说了,哪些代码是可以“被分页”,哪些不行。DDK中又提到了一种很巧的方法(DDK称之为"locked-on-demand"):把部分上面提到的"cannot be"分页的代码也使用这个宏放到分页内存中去,然后再需要的时候使用MmLockPagableCodeSection函数把代码给“锁”到物理内存里去。看到这里的时候我在猜它被“锁”到哪里去,分页内存?非分页?个人觉得还是会“锁到”分页内存里去,然后将这些分页内存置为“不可换出”状态。原因是,通过MmLockPagableCodeSection函数锁定的内存块,在使用完了之后需要相应的调用MmUnlockPagableImageSection函数解锁,如果被“锁”的内存是放在非分页的内存中,那么就不可能有解锁这个操作。
      DDK同时建议:把本身就可分页的代码或数据,与"locked-on-demand"的分开,分成相互独立的section,因为MmLockPagableXXXSection函数锁定的单位是整个section,而不是某个函数。(原文:“Keep purely pageable sections and paged but locked-on-demand sections separate. ”)
      DDK中关于这种技巧,举的例子是CD光驱的驱动,因为CD光驱并不是频繁被使用,所以除了部分必须放在物理内存中的代码之外,其他1中提到的“不可分页的代码”都可以先放到分页内存中(实际上也就是虚存中),当CD被使用的时候再“锁”回来。
      学习Sfilter的时候也看到作者几乎把所有的dispatcher都用这个宏放到了分页内存里,确认了一下:所有调用了PAGE_CODE()的函数的确都通过这个宏放到分页内存中。