ошибка LNK2001: неразрешенный внешний символ _fltused в wdk

Я пытаюсь определить переменную типа double в коде C, который будет использоваться в ядре Windows. Код компилируется, но выдает ошибку при линковке. Я пытался использовать libcntpr.lib в исходном файле, а также определить переменную __fltused в коде, но безрезультатно. Я буду очень признателен, если кто-то может помочь мне в том, как использовать это.


wdk
person randy7    schedule 20.09.2012    source источник


Ответы (1)


Не знаю, применимо ли это к текущему WDK, но Уолтер Оней демотивирует использование операций с плавающей запятой в драйверах здесь.

Проблема похуже, чем просто найти нужную библиотеку, к сожалению. Поддержка плавающей запятой компилятором C предполагает, что он будет работать в среде приложения, где вы можете инициализировать сопроцессор, установить некоторые обработчики исключений, а затем взорваться. Также предполагается, что операционная система позаботится о сохранении и восстановлении контекста сопроцессора каждого потока в соответствии с требованиями всех переключений контекста потока, которые происходят с этого момента.

Эти предположения обычно неверны для водителя. Кроме того, поддержка исключений сопроцессора в библиотеке времени выполнения не может работать, потому что отсутствует целая куча инфраструктуры.

В основном вам нужно написать свой код таким образом, чтобы вы инициализировали сопроцессор каждый раз, когда хотите его использовать (не забывайте о KeSaveFloatingPointState и KeRestoreFloatingPointState). Настройте все так, чтобы сопроцессор также никогда не генерировал исключение. Затем вы можете просто определить символ __fltused где-нибудь, чтобы удовлетворить компоновщика. (Все, что обычно делает этот символ, — это перетаскивание поддержки во время выполнения. Вам не нужна эта поддержка, потому что, как я уже сказал, она не будет работать в режиме ядра.) Вам, несомненно, понадобится некоторый код на языке ассемблера для шагов инициализации.

Если у вас есть системный поток, который будет выполнять всю вашу математику с плавающей запятой, вы можете инициализировать сопроцессор один раз в начале потока. С этого момента система будет сохранять и восстанавливать ваше состояние по мере необходимости.

Не забывайте, что вы можете работать с плавающей запятой только при IRQL ‹ DISPATCH_LEVEL.

Среди прочего есть ФИНИТ. Если вы заржавели в программировании сопроцессора, я бы посоветовал сообщить вашему руководству, что это специализированная проблема, решение которой потребует серьезного изучения. Затем улететь на Мартинику на неделю или около того (то есть после сезона ураганов), чтобы провести исследование в соответствующих условиях.

Серьезно, если вы не знакомы с FINIT и другими инструкциями математического сопроцессора, вероятно, это не то, что вам следует включать в свой драйвер.

Есть также интересное чтение от Microsoft: C++ для драйверов режима ядра: Плюсы и минусы

В системах x86 модули с плавающей запятой и мультимедиа недоступны в режиме ядра, если это специально не запрошено. Попытка их неправильного использования может вызвать или не вызвать ошибку с плавающей запятой при повышенном IRQL (что приведет к сбою системы), но может привести к скрытому повреждению данных в случайных процессах. Неправильное использование также может привести к повреждению данных в других процессах; такие проблемы часто трудно отлаживать.

person huysentruitw    schedule 23.10.2012