4

我正在尝试在将在 Windows 内核中使用的 C 代码中定义双数据类型变量。代码编译但在链接时出错。我尝试在源文件中使用 libcntpr.lib 并在代码中定义 __fltused 变量但无济于事。如果有人可以帮助我如何使用它,我将不胜感激。

4

1 回答 1

7

不知道是否仍然适用于当前的 WDK,但 Walter Oney 在此处不鼓励在驱动程序中使用浮点内容。

不幸的是,这个问题比仅仅找到合适的库还要糟糕。C 编译器的浮点支持假定它将在一个应用程序环境中运行,您可以在其中初始化协处理器,安装一些异常处理程序,然后爆炸。它还假定操作系统将按照从那时起发生的所有线程上下文切换的要求来保存和恢复每个线程的协处理器上下文。

这些假设在驱动程序中通常不成立。此外,对协处理器异常的运行时库支持无法正常工作,因为缺少一大堆基础设施。

您基本上需要做的是以每次要使用协处理器时都初始化协处理器的方式编写代码(不要忘记 KeSaveFloatingPointState 和 KeRestoreFloatingPointState)。进行设置,使协处理器也永远不会产生异常。然后,您可以简单地在某处定义符号 __fltused 以满足链接器的要求。(该符号通常所做的只是拖入运行时支持。您不需要该支持,因为正如我所说,它在内核模式下不起作用。)您无疑需要一些汇编语言代码来执行初始化步骤。

如果您有一个系统线程将执行所有浮点数学运算,则可以在线程开始时初始化协处理器一次。从那时起,系统将根据需要保存和恢复您的状态。

不要忘记您只能在 IRQL < DISPATCH_LEVEL 处进行浮点运算。

除其他外,还有 FINIT。如果您对协处理器编程不熟悉,我的建议是告诉您的管理层这是一个需要大量研究才能解决的专业问题。然后飞往马提尼克岛一周左右(即在飓风季节之后),在适当的环境中进行研究。

说真的,如果您不熟悉 FINIT 和其他数学协处理器指令,那么您可能不应该将其合并到驱动程序中。

微软也有一篇有趣的读物:C++ for Kernel Mode Drivers: Pros and Cons

在 x86 系统上,浮点和多媒体单元在内核模式下不可用,除非特别要求。尝试不正确地使用它们可能会或可能不会在提高的 IRQL 处导致浮点错误(这会导致系统崩溃),但它可能会导致随机进程中的静默数据损坏。使用不当也会导致其他进程的数据损坏;此类问题通常难以调试。

于 2012-10-23T13:17:03.413 回答