В тот момент, когда поток чтения на сервере вызывает ReadFile, поток записи застревает в WriteFile.
На канал ссылаются два объекта файла ядра (см. FILE_OBJECT
), по одному на каждом конце трубы. На стороне сервера CreateNamedPipe
внутренне вызывает собственную системную функцию NtCreateNamedPipeFile
, которая в ядре вызывает IoCreateFile
, при этом CreateFileType
передается какCreateFileTypeNamedPipe
.
Каждый файловый объект может быть открыт для синхронного или асинхронного ввода-вывода . (Асинхронный ввод / вывод также называется перекрывающимся вводом / выводом.) Режим ввода / вывода определяется наличием флага FO_SYNCHRONOUS_IO
в объекте файла. Если флаг установлен, режим ввода / вывода является синхронным. В противном случае режим ввода-вывода является асинхронным.
В синхронном режиме менеджер ввода-вывода сериализует все операции ввода-вывода с файловым объектом. Параллельные операции ввода-вывода над файлом в других потоках будут блокироваться (т. Е. Ждать начала) до завершения текущей операции. Даже запрос имени файла (также операция ввода / вывода) заблокирует. (Это известная проблема для инструментов системного уровня, таких как Sysinternals handle.exe. Она может блокироваться, если мы попытаемся запросить имя канала, пока система ожидает завершения синхронного чтения.)
Использование несколькихтемы (например, чтение в одной теме, запись в другой) здесь не помогает вообще. Асинхронный ввод / вывод здесь идеален. Он более эффективен (меньше потоков) и никогда не блокируется.
Собственный NT API и Windows API используют различные параметры для задания режима ввода / вывода.
NT API (например, NtCreateFile
, NtCreateNamedPipeFile
) по умолчанию предполагает асинхронный режим. Использование синхронного режима требует определенной опции создания, как описано в документации:
Флаги FILE_SYNCHRONOUS_IO_ALERT
и FILE_SYNCHRONOUS_IO_NONALERT
CreateOptions , которые являются взаимоисключающими, как следует из их имен,укажите, что все операции ввода-вывода в файле будут синхронными, если они выполняются через объект файла, на который ссылается возвращенный FileHandle. Все операции ввода-вывода в таком файле сериализуются во всех потоках с использованием возвращенного дескриптора.
При любом из параметров создания в объекте файла устанавливается флаг FO_SYNCHRONOUS_IO
. FILE_SYNCHRONOUS_IO_ALERT
дополнительно устанавливает флаг FO_ALERTABLE_IO
.
API Windows (например, CreateFileW
, CreateNamedPipeW
, CreatePipe
) по умолчанию предполагает режим синхронного ввода-вывода. Для этого он передает опцию создания NT FILE_SYNCHRONOUS_IO_NONALERT
при вызове базовых функций NT API. Флаг Windows API FILE_FLAG_OVERLAPPED
переопределяет значение по умолчанию для запроса режима асинхронного ввода-вывода.