Я пытаюсь определить переменную типа double в коде C, который будет использоваться в ядре Windows. Код компилируется, но выдает ошибку при линковке. Я пытался использовать libcntpr.lib в исходном файле, а также определить переменную __fltused в коде, но безрезультатно. Я буду очень признателен, если кто-то может помочь мне в том, как использовать это.
ошибка LNK2001: неразрешенный внешний символ _fltused в wdk
Ответы (1)
Не знаю, применимо ли это к текущему WDK, но Уолтер Оней демотивирует использование операций с плавающей запятой в драйверах здесь.
Проблема похуже, чем просто найти нужную библиотеку, к сожалению. Поддержка плавающей запятой компилятором C предполагает, что он будет работать в среде приложения, где вы можете инициализировать сопроцессор, установить некоторые обработчики исключений, а затем взорваться. Также предполагается, что операционная система позаботится о сохранении и восстановлении контекста сопроцессора каждого потока в соответствии с требованиями всех переключений контекста потока, которые происходят с этого момента.
Эти предположения обычно неверны для водителя. Кроме того, поддержка исключений сопроцессора в библиотеке времени выполнения не может работать, потому что отсутствует целая куча инфраструктуры.
В основном вам нужно написать свой код таким образом, чтобы вы инициализировали сопроцессор каждый раз, когда хотите его использовать (не забывайте о KeSaveFloatingPointState и KeRestoreFloatingPointState). Настройте все так, чтобы сопроцессор также никогда не генерировал исключение. Затем вы можете просто определить символ __fltused где-нибудь, чтобы удовлетворить компоновщика. (Все, что обычно делает этот символ, — это перетаскивание поддержки во время выполнения. Вам не нужна эта поддержка, потому что, как я уже сказал, она не будет работать в режиме ядра.) Вам, несомненно, понадобится некоторый код на языке ассемблера для шагов инициализации.
Если у вас есть системный поток, который будет выполнять всю вашу математику с плавающей запятой, вы можете инициализировать сопроцессор один раз в начале потока. С этого момента система будет сохранять и восстанавливать ваше состояние по мере необходимости.
Не забывайте, что вы можете работать с плавающей запятой только при IRQL ‹ DISPATCH_LEVEL.
Среди прочего есть ФИНИТ. Если вы заржавели в программировании сопроцессора, я бы посоветовал сообщить вашему руководству, что это специализированная проблема, решение которой потребует серьезного изучения. Затем улететь на Мартинику на неделю или около того (то есть после сезона ураганов), чтобы провести исследование в соответствующих условиях.
Серьезно, если вы не знакомы с FINIT и другими инструкциями математического сопроцессора, вероятно, это не то, что вам следует включать в свой драйвер.
Есть также интересное чтение от Microsoft: C++ для драйверов режима ядра: Плюсы и минусы
В системах x86 модули с плавающей запятой и мультимедиа недоступны в режиме ядра, если это специально не запрошено. Попытка их неправильного использования может вызвать или не вызвать ошибку с плавающей запятой при повышенном IRQL (что приведет к сбою системы), но может привести к скрытому повреждению данных в случайных процессах. Неправильное использование также может привести к повреждению данных в других процессах; такие проблемы часто трудно отлаживать.