为什么我们可以在DISPATCH LEVEL或以上的非分页池中访问内存

时间:2013-09-12 12:24:23

标签: windows kernel driver ndis wdm

据我所知,如果IRQL级别是分派,那么您可以从非分页池访问内存。如果我们将尝试从分页池访问内存。只是想知道为什么?

1 个答案:

答案 0 :(得分:5)

"为什么我们可以在DISPATCH LEVEL及以上的非分页池中访问内存"是一个声明,问题是为什么我们无法从分页池IRQL访问内存> = DISPATCH_LEVEL?

嗯...

  

"任何运行大于IRQL APC_LEVEL的例程都可以   既不从分页池分配内存也不在分页中访问内存   安全地游泳。如果IRQL运行的例程大于APC_LEVEL   导致页面错误,这是一个致命的错误。"

- http://msdn.microsoft.com/en-us/library/windows/hardware/ff554368(v=vs.85).aspx

为什么:

假设您的驱动程序正在处理中断,而在此处,它会保持旋转锁定。现在,您希望访问驻留在页面缓冲池中的某些数据结构,并且由于运气不佳,该数据位于已由内存管理器分页的页面上。

现在,您的驱动程序必须等到内存管理器页面输入您的数据。你正在阻止/等待/睡觉,实际上你的司机是。

现在,又发生了另一个中断,但由于您仍在等待数据被分页,您认为现在会发生什么?

知道这一点,

  

"持有不必要的长时间旋转锁可能会受到伤害   全系统的表现。"

当你的驱动程序等待更长时间发生某事时,你的内核将会冻结。

另外,

  

"请注意,在持有自旋锁时线程可能不会阻塞,因为   这可能会导致死锁。此外,在给定的情况下禁用抢占   处理螺旋锁时的处理器。"

- https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KernelProgramming/synchronization/synchronization.html

无论如何,请进一步阅读:

  

"在IRQL上运行的驱动程序代码> PASSIVE_LEVEL应该执行为   尽快。例程运行的IRQL越高,   更重要的是调整该例程以获得良好的整体性能   尽快执行。例如,任何调用的驱动程序   KeRaiseIrql应该尽快对KeLowerIrql进行相互调用   它可以。"

- http://msdn.microsoft.com/en-us/library/windows/hardware/ff554368(v=vs.85).aspx

页面错误是需要由内存管理器快速处理的异常。当你的驱动程序持有螺旋锁并保持处理器人质时,该处理器就像现在一样好。

MSDN说:

  

"当驱动程序例程持有自旋锁时,它不会导致硬件   异常或引发软件异常而不降低   系统。换句话说,驱动程序的ISR和任何SynchCritSection   驱动程序在调用KeSynchronizeExecution时提供的例程   不得导致故障或陷阱,例如页面错误或算术   异常,并不能引发软件异常。一个调用的例程   KeAcquireSpinLock或KeAcquireInStackQueuedSpinLock也无法造成   硬件异常或引发软件异常,直到它有   发布了执行自旋锁,不再运行IRQL =   DISPATCH_LEVEL"

- http://msdn.microsoft.com/en-us/library/windows/hardware/ff559854(v=vs.85).aspx

所有这些都回答将会发生什么,或者会发生什么。至于回答为什么我们不能使用上面的分页存储器或在DISPATCH_LEVEL:

  1. 它在大多数情况下导致死锁,在内核世界中是内核崩溃。
  2. 它会在内核中引发延迟,这很糟糕。
  3. 请参阅1,这有点重要。
  4. 我试图获取尽可能多的相关信息,如果你还没有出售,请尝试阅读自旋锁,重入函数,中断处理,分页。尝试阅读Linux,Windows和Apple的操作系统内核。他们都用不同的细节说同样的事情。