Часто приходится слышать о большой армии энтузиастов, дизассемблирующих драйверы Windows и переписывающих их под Linux или BSD. Но, к сожалению, этих энтузиастов не так уж и много. Разнотипного оборудования гораздо больше, тем более что сплошь и рядом приходится сталкиваться с ситуацией, когда на компьютере энтузиаста драйвер работает, а на компьютере пользователя — нет, хотя аппаратные конфигурации этих компьютеров практически идентичны. Драйвер мало написать, его еще нужно отладить, протестировать на большом количестве конфигураций и сопровождать, иначе это будет не драйвер, а просто игрушка. Все это требует затрат времени, поэтому если драйвер создается не для коммерческой выгоды, а для личных нужд, то его надежность и совместимость оставляют желать лучшего.
Составители дистрибутивов проделывают огромную работу, собирая различные драйверы и включая их в свой комплект. Качество тестирования таких драйверов очень невысоко, и даже если в списке поддерживаемого оборудования значится конкретное устройство, никаких гарантий того, что оно заработает, у нас нет. Может быть, подойдет драйвер от другой модели, а может быть, и ничего не подойдет вообще! А ведь без драйверов сидеть скверно.
Виртуальные машины
Прежде чем ставить Linux/BSD задумайтесь — а зачем вам, собственно, все это нужно? Если просто хотите протестировать альтернативную систему, освоить средства разработки или компилировать исходные тексты, то наилучшим выбором будет виртуальная машина, например, VMWare (рис. 8.1). Fedora Core на ней, конечно, будет работать очень медленно (например, на P-III 733 работать вообще невозможно), но Debian с KDE будет "пахать" вполне нормально. Хочешь — разрабатывай программы, хочешь — читай руководства (man pages). Еще и в игры типа Star Wars можно поиграть. Никаких драйверов сверх того, что есть в любом "правильном" дистрибутиве, для этого не потребуется. Большинство разработчиков именно так и поступают. Как ни крути, а любой уважающий себя UNIX-программист вынужден держать на компьютере десяток различных операционных систем, чтобы тестировать свои программы на совместимость. На "живом" компьютере переключения между ними происходят только путем перезагрузки, что не слишком удобно. Виртуальные машины при этом можно переключать в любом порядке и с любой скоростью (главное — это иметь как можно больше памяти!).
Рис. 8.1. Виртуальная машина Linux, работающая в среде Windows
Можно поступить и наоборот. Установить Linux/BSD как базовую систему, a Windows водрузить на виртуальную машину (рис. 8.2). Так как VMWare дает прямой доступ к портам COM, LPT и USB, то подключение сканера, принтера или цифровой камеры к вашей машине перестанет быть проблемой. С этим оборудованием будет работать Windows! Базовая машина UNIX в этом случае получает в свое распоряжение все системные ресурсы, и падения производительности уже не происходит, но появляются другие проблемы. Приложения Windows (например, игры) будут либо сильно тормозить, либо откажутся запускаться совсем, к тому же со всеми остальными типами устройств, например, интегрированной платой WLAN или видеокартой, Windows работать не сможет. А все потому, что VMWare представляет собой "черный ящик", отгороженный от базовой операционной системы толстой стеной эмулятора. Вот если бы существовала возможность предоставить виртуальной машине полный доступ ко всему физическому оборудованию, вот тогда бы... Готовьтесь! Именно такой способ мы и собираемся описать!
Рис. 8.2. Виртуальная машина Windows в среде Linux
Перенос драйверов Windows в Linux/BSD
Начнем с простого, но до сих пор никем не решенного вопроса. Разумеется, на самом-то деле вопрос этот, конечно, уже давно решен, но совсем не так, как следовало бы. Известно, что поддержка разделов NTFS в Linux/BSD представляет собой сплошную проблему. Драйверы, способные осуществлять запись на разделы NTFS, появились совсем недавно, да и то лишь затем, чтобы покрасоваться на выставках. Для реальной работы они непригодны, потому что работают не очень стабильно и страдают множеством ограничений. Сжатые файлы, транзакции и множество других возможностей все еще не поддерживаются. Кроме того, NTFS не стоит на месте и хоть и медленно, но совершенствуется. Можно ли, хотя бы теоретически, написать стопроцентно совместимый драйвер, корректно работающий со всеми новыми версиями NTFS без участия программиста? Этот вопрос совсем не так глуп, как кажется. Для чего программистам тратить силы и время на собственный драйвер, когда под рукой есть уже готовый — NTFS.SYS. Если заставить его заработать под Linux, то все проблемы решатся сами собой.
Несмотря на то, что на уровне ядра между Linux/BSD и Windows существует большое количество различий, но и кое-что общее между ними все-таки имеется. И Windows, и Linux, и BSD работают на процессорах семейства x86 в защищенном режиме, используют страничную организацию виртуальной памяти и, наконец, все они взаимодействуют с оборудованием в строго установленном порядке (через иерархию физических и виртуальных шин). Высокоуровневые драйверы, такие, например, как NTFS.SYS, вообще не работают с оборудованием напрямую и содержат минимум системно-зависимого кода. Почему же тогда драйвер от одной системы не работает в другой? А потому, что интерфейс между ОС и драйвером в каждом случае различен, а также потому, что драйвер использует библиотеку функций, экспортируемых системой, и эти функции у каждой системы свои.
Перенести драйвер Windows в Linux/BSD вполне реально! Для этого даже не потребуется его исходный код. Достаточно лишь написать тонкий и несложный "переходник" между драйвером и операционной системой, принимающий запросы и транслирующий их по всем правилами "этикета", а также перенести библиотеку функций, необходимых драйверу для работы. Конечно, для этого необходимо уметь программировать! Для простых пользователей такой рецепт совершенно не годится, но тут уж ничего не поделаешь. Тем не менее, перенести готовый драйвер намного проще, чем переписать его с нуля. Нам не потребуется проводить кропотливую работу по дизассемблированию оригинального кода, заменяющую собой поиск технической документации (которая либо совсем отсутствует, либо отдается только под подписку о неразглашении, зачастую запрещающую открытое распространение исходных текстов). Наконец, при выходе новых версий драйвера Windows процедура его переноса в Linux/BSD проста до тривиальности — достаточно скопировать новый файл поверх старого файла. Однако все это лишь сухая теория. Перейдем к деталям.
Модель ядра Windows NT и всех производных от нее операционных систем (включая Windows 2000, XP, 2003, Longhorn) достаточно проста (рис. 8.3). С "внешним" миром ядро связывает диспетчер системных сервисов, "подключенный" к NTDLL.DLL, которая находится уже за "скорлупой" ядра и исполняется в режиме пользователя. Диспетчер системных сервисов, реализованный в NTOSKRNL.EXE, опирается на вызываемые интерфейсы ядра, часть которых реализована в самом файле NTOSKRNL.EXE, а часть — во внешних драйверах, к числу которых, в частности, принадлежит диспетчер питания. Определенный класс драйверов, называемый драйверами устройств и файловой системы, находится в своеобразной "скорлупе" и взаимодействует с диспетчером системных вызовов через диспетчер ввода-вывода, реализованный опять-таки в NTOSKRNL.EXE!
Рис. 8.3. Архитектура систем из семейства Windows NT
Ядро, на котором, как на фундаменте, держатся все вышеупомянутые компоненты, представляет собой просто совокупность низкоуровневых функций, сосредоточенных в NTOSKRNL.EXE. Ниже находится только уровень аппаратных абстракций (Hardware Abstraction Level, HAL). Когда-то у Microsoft была идея разделить ядро на системно-зависимую и системно-независимую части, чтобы упростить перенос Windows на другие платформы. Однако уже во времена Windows NT 4 все перемешалось, и большая часть системно-зависимых функций попала в NTOSKRNL.EXE. На сегодняшний день ситуация такова, что HAL медленно, но неотвратимо умирает. В нем осталось небольшое количество действительно низкоуровневых функций, непосредственно взаимодействующих с оборудованием, например, с портами и с DMA. Но в ядре Linux/BSD есть свои функции для работы с DMA, так что тащить за собой HAL нам совершенно необязательно, тем более что драйверы взаимодействуют с DMA не напрямую, а через диспетчер Plug and Play, который находится в NTOSKRNL.EXE.