Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпора 97.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
778.75 Кб
Скачать

12.2 Асинхронный ввод-вывод и порты завершения

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

В Win32 существует три метода выполнения асинхронного ввода-вывода:

  • Многопоточный ввод-вывод. Каждый поток в процессе или совокупности про­цессов выполняет обычный синхронный ввод-вывод, в то время как другие по­токи могут продолжать работу.

  • Собственно асинхронный ввод-вывод (или ввод-вывод с перекрытием). После начала чтения, записи или другой операции ввода-вывода поток продолжает выполнение. Если потоку для продолжения нужны результаты ввода-вывода, он ожидает сигнала дескриптора либо указанного события.

  • Процедуры завершения (или расширенный ввод-вывод). Когда операция ввода-вывода завершается, система вызывает в потоке указанную процедуру завершения.

Ввод-вывод с перекрытием

В первую очередь для асинхронного ввода-вывода, с перекрытием или расширен­ного, следует установить атрибут перекрытия дескриптора файла или другого объекта. Для этого в вызове CreateFile или другой функции, которая создает файл, имено­ванный объект или другой дескриптор, указывается флаг FILE_FLAG_OVERLAPPED.

Структуры перекрытия в функции LockFileEx можно использовать для ввода-вывода с перекрытием. Эти структуры — необязательные параметры четы­рех функций ввода-вывода (ReadFile, WriteFile, TransactNamedPipe, ConnectNamedPipe), которые потенциально могут блокировать их при завер­шении операции.

Если указать FILE_FLAG_OVERLAPPED в структуре fdwAttrsAndFlags (для CreateFile) или в структуре fdwOpenMode (для CreateNamedPipe), канал или файл должен использоваться только в асинхронном режиме. Ввод-вывод с перекрытием не действует для анонимных каналов.

Структуры перекрытия

Структура перекрытия (указываемая, например, в параметре lpOverlapped функ­ции ReadFile) содержит следующие данные:

  • позицию в файле (64-разрядную), на которой должно начаться чтение или запись;

  • событие (с ручным сбросом), которое будет сгенерировано при завершении операции.

Структура перекрытия выглядит следующим образом:

typedef struct_OVERLAPPED { DWORD Internal; DWORD InternalHigh;

DWORD Offset; DWORD OffsetHigh; HANDLE hEvent;

} OVERLAPPED

Позиция в файле (указатель) занимает два элемента — offset и OffsetHigh, хотя старшая часть обычно равна нулю. Элементы Internal и InternalHigh зарезервиро­ваны для системы и не должны использоваться.

hEvent — дескриптор события (созданный функцией CreateEvent). Событие мо­жет быть именованным или неименованным, но обязательно должно иметь ручной сброс. hEvent может быть равен NULL; в этом случае программа может ожидать сигнала дескриптора файла, который также является объектом синхрониза­ции. Когда hEvent равен NULL, система сообща­ет о завершении работы по дескриптору файла, т.е. дескриптор файла становится объ­ектом синхронизации.

Это событие немедленно сбрасывается (переводится в пассивное состояние) системой, когда программа делает вызов операции ввода-вывода. Когда операция ввода-вывода завершается, событие становится активным.

Отмена операций ввода-вывода с перекрытием

Функция CancelIO, возвращающая логическое значение, отменяет незавершенные операции асинхронного ввода-вывода на указанном дескрипторе (эта функция имеет только один параметр). Все операции, которые вызывающий поток начал на этом де­скрипторе, отменяются. На операции, начатые другими потоками, это не влияет. Код ошибки отмененных операций — ERROR_OPERATION_ABORTED.

Расширенный ввод-вывод с процедурами завершения

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

Как программа может задать процедуру завершения? Существует семейство расширенных функций вво­да-вывода, отличающихся суффиксом Ех, которые имеют дополнительный параметр для адреса процедуры завершения. Расширенные функции чтения и записи — ReadFileEx и WriteFileEx. Кроме того, следует использовать одну из пяти ожидающих функций предупреждения.

  • WaitForSingleObjectEx

  • WaitForMultipleObjectsEx

  • SleepEx

  • SignalObjectAndWait

  • MsgWaitForMultipleObjectsEx

Расширенный ввод-вывод иногда называется вводом-выводом с предупреждением.

Порты завершения ввода-вывода

Порты завершения ввода-вывода объединяют возможности ввода-вывода с перекрытием и возможности независимых потоков и наиболее полезны в серверных программах.

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

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

Первая задача состоит в том, чтобы создать порт завершения ввода-вывода и вне­сти в него дескрипторы с перекрытием.

Управление портами завершения ввода-вывода

Функция CreateIoCompletionPort служит как для создания порта, так и для добавления дескрипторов. Поскольку она должна выполнять две задачи, порядок использования ее параметров довольно сложен.

HANDLE CreateIoCompletionPort ( HANDLE FileHandle,

HANDLE ExistingCompletionPort, DWORD CompletionKey,

DWORD NumberOfConcurrentThreads);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]