2010-01-06 104 views
1

注:这不是一个问题,我遇到,但它是我 就好理解了(只是因为我 想成为一个更好的人,并 人类进一步 的地平线理解)。Win32 DDK:从驱动程序中断调用API是否错误?

Raymond Chenbook的奖金章,

alt text http://ecx.images-amazon.com/images/I/51UE9zCS%2B2L._SL500_AA240_.jpg

雷蒙德给出了声卡驱动程序中错误的例子:

原有的功能,称为在 硬件中断时间,看起来像这样在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); 
    } 
} 

不仅是有零售代码调试吃剩的东西,但它是 在调用硬件中断时间noninterrupt-安全功能 。如果 wsprintf函数曾经得到 丢弃,则系统将在 硬件中断内发生 段不存在的故障,导致很快死亡。

现在,如果我在看那个代码,我不会猜到一个调用库函数wsprintf会是一个问题。如果我的驱动程序代码需要使用Win32 API,会发生什么情况?

什么是段错误?我了解页面错误的概念:我需要的代码位于已交换到硬盘驱动器的页面上,并且需要在代码执行继续之前从硬盘驱动器恢复。当我们处于设备驱动程序的中断时,什么是segment fault

页面错误保护模式相当于段故障的?如何避免段错误? Windows是否换出设备驱动程序代码?我将如何阻止“wsprintf被丢弃”?什么会导致wsprintf被“丢弃​​”?什么是“丢弃”?丢弃的优点是什么?什么时候发生什么un丢弃

为什么从一个驱动程序里调用一个API调用不好,以及如何解决它?

+0

请注意,上面的MIDI东西是不是司机的东西。使用MIDI堆栈的代码在用户模式下运行100%,因此下面答案中的大部分注释并不特别相关。 – 2010-01-07 01:01:10

+0

我不想抄袭太多雷蒙德的书,但故事开头,称它从Windows 95推出的时代是 - 遥想当年PC蜂鸣器是由8254 PIC运行:P – 2010-01-07 01:24:15

回答

3

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

Windows在某些情况下无法处理页面错误,其中一个处于中断状态。这只是它设计的方式。例如,假设你在从磁盘驱动器读取内存页数据的代码中出现页面错误,怎么可能处理这种情况?所以他们对什么样的操作模式允许页面定义和什么不是定义有一些限制。如果在中断中导致页面错误,内核将强制发生BSOD。

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

至于司机的东西,你可以标记你的一些代码作为非分页的,你可以分配非分页池是内存,你可以在不引起页面错误访问。 wsprintf可以被分页,因为没有人使用它并且内核回收内存。

+0

是* wsprintf *的一部分“我的代码”,我可以标记不可分页?还是它坚持可分页? – 2010-01-06 21:00:48

+0

@IanBoyd:SDK包含源代码,因此您可以编译自己的库并将其标记为可分页。 – 2012-11-04 19:01:49