Реферат: Эффективная многопоточность

// хендл порта завершения ввода/вывода

HANDLE CompletionPort,

// количество переданных байт

LPDWORD lpNumberOfBytes,

// ключ завершения

PULONG_PTR lpCompletionKey,

// структура OVERLAPPED

LPOVERLAPPED *lpOverlapped,

// значение таймаута

DWORD dwMilliseconds

);

Эта функция блокирует поток до тех пор, пока порт не передаст потоку пакет запроса или не истечет таймаут.

Поместить пакет запроса в порт можно с помощью функции PostQueuedCompletionStatus.

BOOL PostQueuedCompletionStatus(

HANDLE CompletionPort, // хендл порта завершения ввода/вывода

DWORD dwNumberOfBytesTransferred, // количество переданных байт

ULONG_PTR dwCompletionKey, // ключ завершения

LPOVERLAPPED lpOverlapped // структура OVERLAPPED

);

Пакет запроса не обязательно должен быть структурой OVERLAPPED или производной от нее [2].

Давайте соберем всю информацию воедино. Порт завершения – объект, организующий несколько очередей из клиентских запросов и потоков, их обрабатывающих. Поток добавляется в очередь ожидающих запрос потоков порта при вызове функции GetQueuedCompletionStatus. При поступлении запроса порт разблокирует первый поток в очереди ждущих потоков и передает ему этот запрос (в виде структуры OVERLAPPED и ключа завершения). Поток при этом перемещается в очередь активных потоков (число активных потоков увеличивается на 1). Предположим, у нас максимальное число активных потоков равно 1, тогда при поступлении следующего запроса другой поток из очереди ожидающих активирован не будет. После обработки клиентского запроса поток вновь вызывает GetQueuedCompletionStatus и ставится в начало списка ожидающих потоков. Почему поток ставится именно в начало списка? Дело в том, что потоки берутся из начала списка, и при низкой активности могут использоваться не все потоки. При этом стеки и контексты не используемых потоков могут быть выгружены на диск за ненадобностью.

Если в процессе обработки запроса поток обратился к блокирующей функции, число активных потоков уменьшается на 1, как если бы поток перешел снова в очередь ожидающих потоков. Это дает возможность при приходе следующего клиентского запроса задействовать следующий поток из очереди ожидающих. Когда первый поток закончит блокирующую операцию, число активных потоков превысит максимальное, и при следующем вызове функции GetQueuedCompletionStatus один из этих потоков заблокируется, а второй получит пакет запроса (если он имеется).

Очередь Запись добавляется при: Запись удаляется при:
Список устройств, ассоциированных с портом вызове CreateIoCompletionPort закрытии хенда файла
Очередь клиентских запросов (FIFO) завершении асинхронной операции файла, ассоциированного с портом, или вызове функции PostQueuedCompletionStatus передаче портом запроса потоку на обработку
Очередь ожидающих потоков вызове функции GetQueuedCompletionStatus начале обработки клиентского запроса потоком
Список работающих потоков начале обработки клиентского запроса потоком вызове потоком GetQueuedCompletionStatus или какую-либо блокирующей функции
Список приостановленных потоков вызове потоком какой-либо блокирующей функции выходе потока из какой-либо блокирующей функции

Таблица 1. Список очередей порта завершения ввода/вывода [1].

Недокументированные возможности порта и его низкоуровневое устройство

Как всегда это бывает у Microsoft, порт завершения обладает многими недокументированными возможностями:

У порта завершения ввода/вывода может быть имя, и соответственно, он доступен для других процессов. Совершенно непонятно, почему разработчики решили скрыть эту, на мой взгляд, нужную особенность порта. Имя можно задать в параметре ObjectAttributes функции NtCreateIoCompletion.

Вторая особенность вытекает из первой: с портом может быть связан дескриптор безопасности, который также задается в параметре ObjectAttributes функции NtCreateIoCompletion.

Открывается порт с помощью функции NtOpenIoCompletion. При вызове функции нужно указать имя порта и уровень доступа. В качестве уровня доступа можно указывать все стандартные и следующие специальные права [2] (таблица 2).

Символическое обозначение Константа Описание
IO_COMPLETION_QUERY_STATE 1 Необходим для запроса состояния объекта "порт"
IO_COMPLETION_MODIFY_STATE 2 Необходим для изменения состояния объекта "порт"

Таблица 2.

К-во Просмотров: 412
Бесплатно скачать Реферат: Эффективная многопоточность