Разработка драйверов для 64-битных версий Windows
- Введение
- Основные положения
- Потенциальные проблемы в коде
- Инструменты
- Заключение
- Библиографический список
В статье рассматриваются вопросы, связанные с выпуском драйверов для 64-битных версий Windows. Приводятся типовые проблемы и пути их решения, а также рассматриваются инструменты, упрощающие процесс разработки драйверов.
Введение
Выход в 2005 году первой версии операционной системы Windows для 64-битных процессоров AMD64 поставил перед разработчиками драйверов новую задачу - выпуск драйверов и для 32-битных, и для 64-битных систем. В то время многие производители оказались не готовы к поддержке драйверов для двух систем, поэтому многие устройства так и не получили обновленных драйверов. Тогда это было оправдано, поскольку 64-битные системы были в новинку и не так уж много пользователей их оценило. Однако с выходом Windows Vista x64 ситуация резко изменилась. Теперь и домашние пользователи хотят иметь 64-битную операционную систему, и разработчикам уже необходимо в обязательном порядке задуматься о выпуске 64-битных версий драйверов.
Прежде всего, возникает вопрос: Нужно ли разрабатывать 64-битные драйверы для 64-битных версий Windows? Ответ однозначен: "Да, нужно!". Дело в том, что использовать 32-битные драйверы на 64-битной системе в режиме ядра невозможно.
При разработке драйверов для 64-битных систем нужно учесть некоторые особенности, игнорирование которых впоследствии может привести к долгим попыткам понять, почему те или иные вещи работают не так, как раньше. MSDN достаточно полно освещает вопрос разработки 64-битных драйверов. Однако, иногда информация оказывается слишком разрозненной. Поэтому в данной статье представлен обзор основных проблем и направлений для дальнейшего изучения вопроса.
Основные положения
При разработке драйверов для Win64 обычно желательно использовать тот же самый исходный код, что и для Win32. Различия в коде стоит выносить в отдельные секции под условной компиляцией.
Перечислим несколько наиболее важных положений, касающихся 64-битных драйверов:
- Поддержка режима DMA (Direct Memory Access). Включение в драйвер поддержки 64-битной адресации позволяет значительно повысить производительность.
- Поддержка 32-битного ввода-вывода. Если драйвер использует процедуры DMA корректно в Windows 2000, то драйвер будет нормально работать и в 64-битных системах.
- Драйвер должен поддерживать как 32-битные так и 64-битные версии команд IOCTL.
Необходимо заметить, что Microsoft максимально возможно обеспечивает разработчиков руководствами по переносу кода в новых версиях Windows DDK.
Потенциальные проблемы в коде
Список потенциальных проблем при переносе кода приведен в [1, 2]. Однако, там лишь названы эти проблемы, мы же подробно рассмотрим варианты их решения.
Итак, MSDN рекомендует нам использовать:
- Новые типы данных, безопасные с точки зрения Win64. Это, прежде всего, типы фиксированной длины, а также типы, предназначенные специально для хранения указателей.
- Корректные строки формата в printf-подобных функциях. Поскольку размеры указателей на 32-битных и 64-битных системах разные, то использовать одну и ту же строку формата не получится. Идеальным решением здесь является отказ от использования таких функций взамен использования их более безопасных аналогов.
- При необходимости обрезать указатель, использовать функции PtrToLong и PtrToUlong. Однако, лучше переписать код так, чтобы подобная операция вовсе не потребовалась. Дело в том, что указатель после такой операции станет уже некорректным.
- Использовать макросы FIELD_OFFSET и TYPE_ALIGNMENT вместо явного вычисления позиции переменной в структуре или ручного учета выравнивания. Это связано опять же с различными типами выравнивания и размерами указателей.
Особое внимание следует обращать на:
- Операции с участием знаковых и беззнаковых переменных. Вопросы приведения типов переменных часто вызывают непонимание, поэтому лучше стараться их избегать.
- Вызовы функций, где один из параметров является указателем. Причем потенциальная ошибка может быть скрыта как внутри функции, так и вне ее, при использовании результата ее работы.
- Использование магических констант, которые могут изменяться в зависимости от разрядности системы. Обратите внимание, что число -1 на 64-битной системе уже не равно 0xffffffff, как это было на 32-битной. Чему оно равно? Разумеется, 0xffffffffffffffff, в то время как 0xffffffff - это всего лишь 0x00000000ffffffff.
- Структуры, содержащие указатели. Так как изменения адресного пространства, произошедшие на 64-битных системах, могут напрямую сказаться на работе драйверов.
- Приведение указателей к каким-либо типам данных (int, long).
Инструменты
Для проверки работоспособности драйверов рекомендуется использовать соответствующие инструменты. Помимо включения максимального уровня диагностики в компиляторе (/W4 или даже /Wall) обязательно необходимо использовать другие возможности.
Прежде всего, посмотрите на бесплатный инструмент от Microsoft - анализатор PREfast, если Вы еще с ним не знакомы. Это статический анализатор кода, который обнаруживает некоторые классы ошибок, которые часто встречаются как в драйверах, так и в обычных C и C++ программах.
Статический анализатор кода общего назначения Gimpel Software PC-lint обнаруживает, помимо некоторых из перечисленных ошибок, еще и огромное количество ошибок, встречающихся в обычных программах.
Другой статический анализатор кода Viva64 предназначен для поиска ошибок в C++ программах, проявляющихся при переносе кода с 32-битных на 64-битные системы.
Заключение
Как видите, ничего страшного в разработке 64-битных драйверов нет и инструменты, облегчающие этот процесс, доступны. А значит откладывать это больше не стоит.
Библиографический список
- Designing for 64-bit Windows.
https://msdn.microsoft.com/en-us/library/windows/hardware/dn613903(v=vs.85).aspx.
- Porting Issues Checklist. https://msdn.microsoft.com/en-us/library/ff559744.aspx.