
- •1.1 Основы программирования в операционной системе Windows
- •1.1.1 Вызов функций api
- •1.1.2 Структура программы
- •1.2 Вопросы системного программирования в Windows
- •1.2.1 Страничная и сегментная адресация.
- •1.2.2 Адресное пространство процесса.
- •2.1 Управление процессами
- •2.2 Процессы и потоки в Windows
- •2.3 Создание процессов
- •2.4 Определение исполняемого образа и командной строки
- •2.5 Идентификация процессов
- •3.1 Создание потока. Функция CreateThread
- •3.2. Завершение потока
- •3.3 Другие функции работы с потоками
- •3.4 Структура context
- •3.5 Приоритеты потоков
- •4.1 Объект critical_section
- •4.2 Мьютексы
- •4.3 Семафоры
- •5.1 События
- •7.1 Кучи
- •7.2 Управление памятью кучи
- •Другие функции для работы с кучей
- •Резюме по управлению кучей
- •Отображение адресного пространства процесса в объекты отображения
- •Что такое импорт
- •Явная загрузка dll
- •Явное подключение экспортируемого идентификатора
- •10.1 Управление файлами и каталогами Создание и открытие файлов
- •10.2 Управление каталогами
- •10.3 Другие методы получения атрибутов файлов и каталогов
- •11.1 Блокировка файлов
- •11.2 Реестр
- •12.1 Стандартные устройства и консольный ввод-вывод
- •12.2 Асинхронный ввод-вывод и порты завершения
- •Параметры
- •Цели системы безопасности
- •Параметры
- •Аварийное завершение
- •Использование именованных каналов
- •Параметры
- •Наблюдение за сообщениями в именованном канале
- •Параметры
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);