|
#11
|
|||
|
|||
Цитата:
Однако не все так плохо, и подобный трюк все-таки работает под XP. Дело в том, что привилегии для кода выполняемого в пользовательском режиме гибко настраиваются. Привилегии процесса задаются табличным способом. К каждому процессу привязан набор таблиц, отвечающих за привилегии, виртуальную память и т.д. В том числе есть и таблица, отвечающая за доступ к портам ввода-вывода (I/O Permission Map). Естественно, что по умолчанию доступ ко всей аппаратуре для приложений закрыт. Также пользовательским приложениям запрещена работа с таблицами привелегий. Но разрешена для драйверов. К счастью, такие драйвера уже давно написаны. Самый простой - это giveio.sys, он дает открывшему его приложению доступ ко всему диапазону портов ввода вывода. Принцип работы giveio.sys простой: 1. Сначала нужно установить драйвер в систему. Это можно сделать многими способами. Например специальной утилитой (LoadDrv.exe). Еще можно загрузить драйвер прямо из программы, воспользовавшись функциями API. Это достаточно сделать один раз, в дальнейшем драйвер будет загружаться вместе с системой. 2. Нужно подключиться к драйверу giveio.sys. Драйвер обнаружит это подключение и автоматически разрешит доступ ко всем портам для вызывающего процесса. Подключение к драйверу выполняется через функцию CreateFile. В качестве имени файла нужно передать строку '\\.\giveio'; 3. Все. Доступ к портам для данного процесса открыт. Можно закрывать хэндл драйвера - доступ сохраниться вплоть до завершения работы процесса. Есть и другие подобные драйверы. С их помощью, например, можно открыть доступ не ко всем портам, а лишь к определенному диапазону. Или открыть доступ для другого процесса. Цитата:
Код:
ReadFile(h,ByteValue,1,tmp,nil); // function PortReadByte(Addr:Word):Byte; ReadFile(h,WordValue,2,tmp,nil); // function PortReadWord(Addr:Word) : Word; ReadFile(h,WordValue,2,tmp,nil); // function PortReadWordLS(Addr:Word) : Word; WriteFile(h,ByteValue,1,tmp,nil); // procedure PortWriteByte(Addr:Word; Value:Byte); WriteFile(h,WordValue,2,tmp,nil); // procedure PortWriteWord(Addr:Word; Value:Word); WriteFile(h,WordValue,2,tmp,nil); // procedure PortWriteWordLS(Addr:Word; Value:Word) ReadFile(h,IntValue,4,tmp,nil); // А такую функцию в Port95 еще добавлять надо ;) WriteFile(h,IntValue,4,tmp,nil); // также как и эту Еще осталась неохваченной настройка COM-порта. Ее нужно писать самому, в Port95.pas этого нет. Не надеяться же на то, что порт до нас уже кто-то настроил. Какой-то особенной простоты настройки при прямом доступе к портам нет. Будем считать ничья. Ну и конечно же, мое самое любимое: СКОРОСТЬ!!! Казалось бы - ассемблерные функции. Да там тормозить просто нечему!!! Ан нет и тут засада... Есть такая инструкция OUT. Она-то нам всю малину и испортила. Больно уж долго выполняется (быстрее скорости порта не разгонишься, а это очень медленно даже для систем 20-летней давности). А дальше оптимизировать уже некуда - и так две инструкции. Еще момент: [ситуация] оборудование попалось настырное - шлет и шлет данные непрерывным потоком на полной скорости. Скорость приема байт хоть и небольшая (каких-то 10 кГц всего), но и квант времени в системе немаленький - 18 миллисекунд. Кто-то процессор занял чуть дольше положенного - и PortReadByte не выполнялся в течении 10 мс. Хорошо что есть буфер FIFO! Целых 16 байт. На 16 мс. Мда, уже не хватает - могут быть потери данных (вот она проклятая многозадачность где боком вылезла) - надо что-то думать... А в WinAPI - дописал 100 строк сложного кода и у тебя как-то все само-собой в буфере появляется - успевай только обрабатывать. Последний раз редактировалось Lucky192, 05.10.2011 в 04:30. |