1

注意:这不是我遇到的问题,但这是我想了解的事情(只是因为我想成为一个更好的人,并进一步扩大人类理解的视野)。

Raymond Chen的附赠章节中,

替代文字

Raymond 给出了声卡驱动程序中的错误示例:

在硬件中断时调用的原始函数在 DDK 中如下所示:

void FAR PASCAL midiCallback(NPPORTALLOC pPortAlloc, WORD msg,
                             DWORD dwParam1, DWORD dwParm2) {
   if (pPostAlloc->dwCallback)
      DriverCallBack(pPortalloc->dwCallback, HIWORD(pPortalloc->dwFlags),
                     pPortalloc->hMidi, msg, dwParam1, dwParam2);
}

他们的函数版本如下所示:

void FAR PASCAL midiCallback(NPPORTALLOC pPortAlloc, WORD msg,
                               DWORD dwParam1, DWORD dwParm2) {
   char szBuf[80];

   if (pPostAlloc->dwCallback) {
      wsprintf(szBuf, " Dc(hMidi=%X,wMsg=%X)", pPortalloc->hMidi, msg);
#ifdef DEBUG
   OutputDebugString(szBuf);
#endif
      DriverCallBack(pPortalloc->dwCallback, HIWORD(pPortalloc->dwFlags),
                     pPortalloc->hMidi, msg, dwParam1, dwParam2);
   }
} 

零售代码中不仅有剩余的调试内容,而且还在硬件中断时调用非中断安全函数。如果 wsprintf函数被丢弃,系统将在硬件中断中出现段不存在故障,从而导致相当快的死亡。

现在,如果我正在查看该代码,我不会猜到调用库函数wsprintf会是一个问题。如果我的驱动程序代码需要使用 Win32 API 会怎样?

什么是段故障?我理解页面错误的概念:我需要的代码位于已换出到硬盘驱动器的页面上,并且需要在代码执行继续之前从硬盘驱动器返回。当我们在设备驱动程序的中断中时,什么是段错误?

页面错误是段错误保护模式吗?如何避免段错误?Windows 是否会换出设备驱动程序代码?我将如何阻止“ wsprintf 被丢弃”?什么会导致 wsprintf 被“丢弃”?什么是“丢弃”?丢弃有什么好处?当它有东西未被丢弃时

为什么从驱动程序内部调用 API 调用不好,如何解决它?

4

1 回答 1

3

分段错误通常是指无效的内存访问。在大多数现代操作系统中,产生段错误的机制也用于提供请求分页机制。他们倾向于做的是将内存页面“交换”到磁盘并将它们标记为无效,下次指令访问该内存位时,内核会识别它并不是真正的错误并将在内存中分页。

Windows 无法在某些上下文中处理页面错误,其中之一处于中断状态。这就是它的设计方式。例如,假设您在从磁盘驱动器读取内存页面数据的代码中遇到页面错误,它如何处理这种情况?因此,他们对允许分页和不允许分页的操作模式定义了某些限制。如果您在中断中导致页面错误,内核将强制执行 BSOD。

如果你需要做一些可能需要分页的事情,你应该在中断上下文中做的是在中断处理程序中将所谓的延迟过程调用 ( DPC ) 排队。然后在 DPC 级别执行 DPC(如果您阅读了 DDK 函数的一些描述,您会看到提到的内容)。DPC 级别可以分页,因此您可以使用所需的任何功能。

至于驱动程序的东西,您可以将一些代码标记为不可分页,并且您可以分配非分页池,这是您可以访问而不会导致页面错误的内存。wsprintf 可能会被调出,因为没有人使用它并且内核回收了内存。

于 2010-01-06T19:06:53.620 回答