Читаем Серверные технологии хранения данных в среде Windows® 2000 Windows® Server 2003 полностью

Асинхронный вызов процедуры (asynchronous procedure call – АРС) немного похож на вызов отложенной обработки, но существуют и заметные различия. Как и вызов отложенной обработки, АРС выполняется на уровне привилегий, превышающем уровень привилегий обычного кода. В отличие от вызова отложенной обработки, выполняемого в контексте произвольного процесса, асинхронный вызов процедуры всегда выполняется в контексте определенного процесса. Таким образом, асинхронный вызов процедуры требует больших затрат, чем вызов отложенной обработки, так как приходится сохранять и восстанавливать большее количество параметров. Читателю, знакомому с операционными системами UNIX, асинхронные вызовы процедур напомнят процедуры обработки сигналов UNIX.

Существует два типа АРС: вызов в режиме ядра и вызов в пользовательском режиме. Асинхронный вызов процедуры в режиме ядра связан с драйвером или другим кодом режима ядра и обычно используется для передачи данных, например для копирования данных из буфера ядра в пользовательский буфер. Помните, что пользовательский буфер должен быть доступен в контексте процесса, который владеет буфером.

Код пользовательского режима тоже может использовать асинхронный вызов процедур. Для этого необходим прикладной интерфейс программирования QueueUserAPC, который рассматривается в документации к набору Platform SDK. Асинхронные вызовы процедур в пользовательском режиме предоставляются только тогда, когда поток получает предупреждение, например при блокировании в результате вызова функций WaitForSingleObject или WaitForMultipleObject. Подробная информация об этих функциях доступна в документации Platform SDK. Достаточно сказать, что эти функции позволяют организовать синхронизацию потоков.

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

<p><strong>1.6 Драйверы и буферы ввода-вывода</strong></p>

В этом разделе рассматриваются буферы ввода-вывода, которые уже упоминались ранее в главе. Драйверы используют буферы для осуществления ввода-вывода и управления им (IOCTL). Для этого драйверы посредством соответствующего объекта указывают предпочтительный способ ввода-вывода. Существует три поддерживаемых драйверами Windows NT типа ввода- вывода: буферизированный, прямой и небуферизированный. Эти методы рассматриваются в данном разделе.

1.6.1 Буферизированный ввод-вывод

Буферизированный ввод-вывод обычно используется для передачи меньших объемов данных, так как в процессе ввода-вывода участвуют операции копирования данных. После того как приложение отправило запрос на ввод- вывод, диспетчер ввода-вывода проверяет соответствие прав доступа приложения к предоставленному буферу ввода-вывода (соответствие прав доступа предполагает, что приложение имеет права на чтение и запись, а также имеет доступ к буферу необходимого размера, указанного в запросе на ввод- вывод). Диспетчер ввода-вывода выделяет буфер в невыгружаемой памяти и в случае запроса на запись копирует данные из буфера приложения в выделенный буфер. Этот буфер передается драйверу.

Драйвер не обязан заботиться о контексте потока, так как буфер находится в невыгружаемой памяти и действителен в контексте любого процесса или потока. Драйвер выполняет необходимую операцию ввода-вывода. Для операции чтения драйвер копирует данные в полученный буфер. Кроме того, драйвер может «предположить», что в контексте виртуального адресного пространства буфер будет непрерывным, но, как и в случае других буферов Windows NT, непрерывность буфера в виртуальном адресном пространстве не гарантирует непрерывности в физическом адресном пространстве.

На этом этапе драйвер завершает обработку IRP, и ответственность за копирование данных из невыгружаемого буфера в буфер приложения возлагается на диспетчер ввода-вывода. Эта операция копирования должна выполняться в контексте процесса, который отправил запрос на ввод-вывод. Кроме того, диспетчер ввода-вывода должен освобождать буфер, выделенный в невыгружаемой области памяти.

1.6.2 Прямой ввод-вывод

Прямой ввод-вывод (Direct I/O) несколько более запутан, чем буферизированный, однако намного эффективнее при выполнении операций ввода- вывода для больших массивов данных. Диспетчер ввода-вывода выполняет базовые проверки, например проверяет разрешения приложения на доступ к буферу посредством области ввода-вывода желательного объема. Буфер в памяти, независимый от процесса, описывается для драйвера средствами структуры данных, которая называется список дескрипторов памяти (memory descriptor list – MDL). Адрес буфера используется в качестве общесистемного виртуального адресного пространства.

Перейти на страницу:

Похожие книги