PIPE_NOWAIT
означает, что неблокирующий режим включен на ручке. В этом режиме ReadFile
, WriteFile
и ConnectNamedPipe
всегда завершено немедленно.
Значение FILE_FLAG_OVERLAPPED
означает, что асинхронный режим включен на дескрипторе. Если этот режим включен, все не синхронно io [1] операции всегда немедленно возвращают .
так FILE_FLAG_OVERLAPPED
против PIPE_NOWAIT
- это возврат немедленно против завершено немедленно.
завершено немедленно (что включает возврат немедленно) означает, что операция io уже завершена при возврате API. но наоборот не соответствует действительности. если операция возвращает немедленно, это не означает, что операция завершена уже. если операция еще не завершена ntapi код возврата STATUS_PENDING
. Win32 API в таких ситуациях обычно устанавливает последнюю ошибку на ERROR_IO_PENDING
.
существует 3 способа определения завершения операции ввода-вывода в случае асинхронного режима обработки.
- привязать ручку к IOCP (через
CreateIoCompletionPort
или
BindIoCompletionCallback
или CreateThreadpoolIo
). как результат, когда
io complete - указатель на OVERLAPPED
, который мы передаем io call -
будет поставлен в очередь на IOCP (в случае BindIoCompletionCallback
или
CreateThreadpoolIo
Система самостоятельно создайте IOCP и прослушайте ее
и вызов нашего зарегистрированного обратного вызова, когда указатель на OVERLAPPED
будет
быть в очереди на IOCP )
- некоторые Win32 API, такие
ReadFileEx
или WriteFileEx
и все Ntapi пусть
указать процедуру завершения APC, которая будет вызываться в контексте
поток, который начинает работу io, когда операция io завершена.
В этом случае поток должен делать предупреждающее ожидание. это ожидание не
совместим с дескриптором связывания IOCP
вызов API, если дескриптор файла привязан к IOCP - системный возврат недействителен
ошибка параметра)
- мы можем создать событие и передать его вызову API (через
OVERLAPPED::hEvent
) - в этом случае это событие будет сброшено
система, когда начинается операция IO, и устанавливается в сигнальное состояние, когда IO
операция завершена. в отличие от первых 2 вариантов в этом случае мы имеем
нет дополнительного контекста (в указателе лица на OVERLAPPED
) при вводе
операция завершена. обычно это худший вариант.
[1] существует несколько операций ввода-вывода, которые всегда синхронны API. например GetFileInformationByHandleEx
, SetFileInformationByHandle
. но почти io операции не являются синхронными io. все эти операции ввода-вывода принимают указатель на OVERLAPPED
в качестве параметра. так что если в подписи API нет указателя на OVERLAPPED
- это синхронный вызов API. если существует - обычно асинхронный (исключение CancelIoEx
, например, когда указатель на перекрытие связан не с текущей операцией, а с предыдущей операцией ввода-вывода, которую мы хотим отменить). в частности ReadFile
, WriteFile
, DeviceIoControl
, ConnectNamedPipe
(внутренне это вызов DeviceIoControl
с FSCTL_PIPE_LISTEN
)) не является синхронным io api