Архивы: по дате | по разделам | по авторам

Разрушенные стены

Архив
автор : ПАВЕЛ КИРЮХИН    13.10.1998

Прямой доступ к аппаратным ресурсам из Win32-приложений

Итак, начальник вашей лаборатории решил идти в ногу со временем и установить на компьютере, обслуживающем экспериментальную установку, операционную систему Windows (может быть, даже NT). Аргументов в пользу этого решения много, например возможность использовать мощные пакеты обработки данных, сетевые средства и т. д. Вы же, хотя и имели с Windows дело, все работы с аппаратурой испокон века делали под DOS - на C и ассемблере. Задача, стоящая перед вами, в общем-то, проста и понятна - перенести имеющееся богатство под Windows. Решение же ее совсем не очевидно.

Windows, с точки зрения программиста, представляет собой многослойный пирог, каждый слой которого, в свою очередь, представляет собой некий уровень абстракции для вышележащего слоя. В NT самым нижнем слоем является HAL (hardware abstraction level), а на самом верху находятся многочисленные API, которыми предписано пользоваться программистам. Создатели системы заботливо изолировали вас и ваши программы от прямого общения с аппаратурой. Взаимодействовать с ней разрешено лишь драйверам, работающим в режиме ядра (оно же ring 0). Ваши программы, работающие в режиме пользователя (ring 3), должны специальным образом обращаться к драйверам, которые, в свою очередь, обращаются к аппаратуре. В идеальном случае у вас имеется драйвер для аппаратуры с нужной вам функциональностью под требуемую версию Windows. Однако велика вероятность того, что вы останетесь один на один с программой, железом и возведенной между ними стеной.

Выходов из этой ситуации два: можно или заказать драйвер, или написать его самому. Для реализации второго пути фирмой Microsoft поставляются так называемые DDK (Device Driver Kits) - документация и наборы библиотек и интерфейсов на С, позволяющие компилировать драйверы. Теоретически этого достаточно для написания любого драйвера, но практика показывает, что документация слишком сложна, интерфейсы запутанны, и если скомпилированный пример и работает, то почти такой же ваш драйвер - разрушает систему. Именно поэтому большую популярность приобрели пакеты фирмы Vireo (www.vireo.com) - Driver::Works и VtoolsD. Они предназначены для быстрого создания драйверов в среде Windows 95/98/NT. Основная идея состоит в том, что посредством мастеров (wizards) указываются аппаратные ресурсы, необходимые драйверу, - тип шины, номера прерываний, порты ввода/вывода и т. д. В результате создается скелет драйвера на С или С++. Вам остается дополнить его функциональностью, например вставить свой код в обработчик прерывания.

Но оказывается, доступ к аппаратуре из Windows-программы можно получить без драйвера в классическом смысле этого слова. Ниже будут описаны два продукта, позволяющие совершить этот маленький фокус.

Первый называется Driver::Agent, и создан он все той же Vireo. Приложения для Windows 95/98/NT, созданные с помощью этого продукта, получают доступ к следующим ресурсам: прерывания (можно писать как ISR, так и DPC), порты ввода/вывода, DMA, таймеры однократного и периодического срабатывания, средства межпроцессной синхронизации (IPC, shared events), разделяемая память (shared FIFO), обработчики shutdown. Языки, на которых можно создавать приложения: C, C++, Delphi, Visual Basic, Java. При этом созданные приложения могут исполняться без перекомпиляции в Windows 95/98/NT (при этом в каждой системе должен работать свой Agent Class Driver).

Driver::Agent воплощает идеологию фирмы Vireo: каркас приложения создается с помощью мастера. В диалогах мастера указываются требующиеся аппаратные ресурсы и выбирается язык. Сгенерированный текст (функции или члены классов) дополняется необходимой функциональностью, а затем компилируется. Отладка может происходить в интегрированной среде вашего компилятора.

Принцип работы Driver::Agent состоит в следующем: в режиме ядра действует некий вспомогательный драйвер, которому разрешается обращаться к аппаратуре. Запросы к аппаратным ресурсам из приложения обслуживаются DLL, которая перенаправляет эти запросы драйверу.

У внимательного читателя уже вероятно появился вопрос: а как ISR и DPC работают в режиме пользователя? А они там и не работают! Vireo разработала так называемый Kernel Agent, который позволяет выносить критичные по времени исполнения пользовательские функции в режим ядра, избегая тем самым затрат времени на переключение режимов при каждом обращении к устройству. Пользовательское приложение, если нужно, может получить доступ к этим функциям посредством автоматически генерируемой Proxy DLL. Работа приложений и kernel-функций может синхронизироваться посредством shared events, они могут обмениваться информацией с помощью shared FIFO. Приложения и kernel-функции могут посылать сообщения, которые будут восприниматься специальной утилитой Driver::Monitor. Туда же могут поступать сообщения от драйверов, созданных с помощью Driver::Works. Все это незаменимо при отладке.

В целом Driver::Agent предоставляет уникальную возможность, не вдаваясь в тонкости написания драйверов, создавать программы на наиболее распространенных языках, напрямую работающие с аппаратными ресурсами.

Второй продукт, о котором пойдет речь, создан американской фирмой VenturCom (www.vci.com). Собственно, преследуемые им цели гораздо серьезнее, чем простая работа с аппаратурой, да и стоит он на порядок дороже Driver::Agent. Называется этот продукт RTX (Real-Time eXtension), и предназначен для "превращения" стандартной Windows NT в систему жесткого реального времени. В последнее время RTX наделал немало шума на Западе и пользуется изрядной популярностью.

В его основе лежит следующий подход:

  1. Модифицируется HAL. Это возможно, так как Microsoft предоставляет исходные коды HAL своим партнерам.
  2. В Windows NT устанавливается подсистема реального времени, видимая из NT как драйвер. У этой системы есть собственный планировщик задач.

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

Не вдаваясь в специфику real-time-систем, остановимся на некоторых аспектах программирования для RTX, тем более что легкость и простота создания готовых приложений является одним из козырей VenturCom.

Приложения получают доступ к аппаратуре непосредственно, без всякой предварительной возни с драйверами. VenturCom разработала богатое API, которое условно делит на четыре части. Первая часть состоит из функций, совпадающих по именам и действию с функциями из Win32 API. Вторая - из уникальных функций для работы с аппаратурой (например, RtWritePortUchar(), RtAttachInterruptVector()) и функций, имеющих аналоги в Win32, но работающие несколько иначе (например RtCreateMutex()). Третью часть составляют функции из С-библиотеки времени выполнения. Последнюю (но не по важности) группу образуют функции, называемые Driver IPC API; они используются при написании стандартных драйверов устройств под Windows NT и предназначены для обеспечения синхронизации и обмена сообщениями между драйверами и real-time-процессами.

Сами приложения создаются в MS Visual C++ (хотя, после некоторых ухищрений можно использовать и другой компилятор, например Borland C++ Builder). Один и тот же код может компилироваться двумя способами - либо как Win32-файл с расширением exe, либо как приложение подсистемы реального времени с расширением rtss (для специалистов: в первом случае создаются приложения "мягкого" реального времени, во втором - "жесткого"). Замечательно то, что код пишется и отлаживается (!) в привычной среде Visual Studio.

Пусть, скажем, имеется плата ЦАП/АЦП, в которой по окончании преобразования сигнала в цифровую форму генерируется прерывание. Написание драйвера RTX для такой платы требует всего нескольких функций: RtEnableInterrupts - разрешение прерываний, RtAttachInterruptVector - назначение прерыванию процедуры-обработчика (в RTX прерывания обрабатываются одним потоком, а не разбиваются на ISR и DPC), RtReadPortXXX - для считывания поступивших данных из порта ввода/вывода, и RtWritePortXXX - для записи в порт значения, разрешающего дальнейшие прерывания. Для поддержания получившегося "драйвера" в рабочем состоянии в конце main() надо подвесить поток вызовом Sleep или SuspendThread, или RtWaitForSingleObject. Можно установить точку останова в процедуре обработки прерывания и затем прогнать всю процедуру в стандартном отладчике Visual C. Если теперь скомпилировать отлаженную программу как rtss, то RTX гарантирует, что от момента возникновения аппаратного прерывания до входа в процедуру обработки пройдет не более определенного промежутка времени (например 50 мкс).

Обычно предполагается, что RTX-проект состоит минимум из двух частей - real-time-части, выполняющей критичную по времени работу, и Win32-части, предоставляющей графический интерфейс и осуществляющей взаимодействие с остальными службами и подсистемами Windows NT (обмен по сети, дисковый ввод/вывод и т. д.). Обмен между двумя частями проекта осуществляется посредством разделяемой памяти и развитых средств межпроцессной синхронизации.

Кроме возможности работать с прерываниями и портами ввода/вывода, в RTX предусмотрены таймеры (одноразовые и периодические), средства конфигурирования PCI-шины, возможность проецировать физическое адресное пространство на адресное пространство потока, средства работы с памятью (например запрещение свопинга участка памяти на диск), структурная обработка исключений, обработчик shutdown и blue screen (при возникновении blue screen подсистема реального времени и исполняющиеся в ней потоки продолжают работать - они просто получают возможность реагировать на критическую ситуацию).

Итак, RTX позволяет программисту со знанием Win32 API и языка C и минимальным опытом работы с аппаратурой (хотя бы под DOS) быстро создавать приложения, напрямую работающие с аппаратурой. Real-time-свойства приложений в рамках этой статьи можно рассматривать как дополнительную особенность.

Конечно, RTX и Driver::Agent - продукты разных классов и преследуют разные цели. Помнится, во времена расцвета DOS ее сторонники, чувствуя наступление Windows, говорили, что достаточно просто немного доработать DOS, дополнить ее многозадачностью и сетевыми средствами... И вот на очередном витке спирали развития программных средств мы видим, что полноценные многозадачные ОС могут позволять работать с аппаратурой почти так же просто, как много лет назад это позволяла DOS.

***

Подробную информацию на русском языке о продуктах, описанных в статье, можно найти на сайте компании PLC Systems (www.plcsystems.ru), российского дистрибьютора продукции VenturCom и Vireo.

© ООО "Компьютерра-Онлайн", 1997-2022
При цитировании и использовании любых материалов ссылка на "Компьютерру" обязательна.