3

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

4

1 回答 1

8

“为什么我们可以从 DISPATCH LEVEL 或以上的非分页池访问内存”是一个语句,问题是为什么我们不能从分页池 IRQL >= DISPATCH_LEVEL 访问内存?

出色地...

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

-- 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 和驱动程序在调用 KeSynchronizeExecution 时提供的任何 SynchCritSection 例程都不能导致错误或陷阱,例如页面错误或算术异常,并且不能引发软件异常。调用 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,这很重要。

我已尝试获取尽可能多的相关信息,如果您仍然没有出售,请尝试阅读自旋锁、可重入函数、中断处理、分页。尝试阅读 Linux、Windows 和 Apple 操作系统的内核。他们都说同样的话,但细节不同。

于 2014-04-08T06:52:45.513 回答