据我所知,如果调度 IRQL 级别,那么您可以从非分页池访问内存。如果我们将尝试从分页池访问内存。只是想知道为什么?
1 回答
“为什么我们可以从 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
为什么是这样:
假设您的驱动程序正在处理一个中断,并且在此期间,它持有一个自旋锁。现在,您想要访问位于分页池中的某些数据结构,并且由于您已经不走运了,该数据位于已被内存管理器分页的页面上。
现在,您的驱动程序必须等到内存管理器将您的数据分页。您正在阻塞/等待/睡觉,实际上是您的司机。
现在,又发生了一个中断,但既然你还在等待数据被调入,你认为现在会发生什么?
知道这个,
" 不必要地长时间持有自旋锁会损害系统范围的性能。"
当您的驱动程序等待更长时间以等待某些事情发生时,您的内核将冻结。
还,
“请注意,线程在持有自旋锁时可能不会阻塞,因为这可能导致死锁。此外,在持有自旋锁时,在给定处理器上禁用抢占。”
无论如何,请进一步阅读:
“以 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,这很重要。
我已尝试获取尽可能多的相关信息,如果您仍然没有出售,请尝试阅读自旋锁、可重入函数、中断处理、分页。尝试阅读 Linux、Windows 和 Apple 操作系统的内核。他们都说同样的话,但细节不同。