4.3. Использование перекрывающегося ввода/вывода
Значительно более эффективным способом реализации асинхронного
ввода/вывода в Windows является перекрывающийся ввод/вывод. В Windows
эта разновидность ввода/вывода поддерживается в отношении фактически
всех типов файлов. В частности, вы можете применить перекрывающийся
ввод/вывод в отношении дисковых файлов, коммуникационных портов, име-
нованных каналов (named pipes) и сетевых сокетов. В общем и целом если
в отношении чего-либо можно применить операции ReadFile() и WriteFile(),
значит, при этом допускается использовать перекрывающийся ввод/вывод.
Прежде чем вы сможете осуществлять в отношении файла операции пере-
крывающегося ввода/вывода, необходимо открыть файл при помощи функции
CreateFile() с использованием флага FILE_FLAG_OVERLAPPED. Если этот флаг
не указать, перекрывающийся ввод/вывод будет невозможен. Если флаг установ-
лен, вы не сможете использовать файл обычным способом. При обмене данными
с файлом будет использоваться перекрывающийся ввод/вывод.
Выполняя перекрывающийся ввод/вывод при помощи функций ReadFile()
и WriteFile(), в качестве одного из аргументов вы передаете этим функциям
указатель на структуру OVERLAPPED. Первые два 32-битных слова этой
структуры зарезервированы системой для внутреннего использования. Вторые
два слова могут содержать 64-битное смещение, указывающее на позицию
файла, в которой будет осуществляться чтение или запись данных. Ввод/вывод
осуществляется асинхронно, поэтому не существует гарантий, что данные из
файла будут извлекаться (или записываться) последовательно байт за байтом.
Таким образом, при выполнении перекрывающегося ввода/вывода не сущест-
вует понятия текущей позиции. При выполнении любой операции вы просто
указываете смещение в файле. Если вы работаете с потоками данных (напри-
мер, последовательный порт или сокет), понятие смещения теряет смысл, по-
этому система игнорирует соответствующее поле структуры OVERLAPPED.
Последнее поле структуры OVERLAPPED – это дескриптор события. Впро-
чем, его можно не указывать (присваивать NULL).
Когда происходит обращение к функции асинхронного ввода/вывода,
система может завершить процедуру ввода/вывода немедленно. Например, вы
можете приказать системе выполнить чтение одного байта из последователь-
ного устройства и записать этот байт в 30-байтный буфер, ожидающий ввода.
В этом случае функция ввода/вывода завершает свою работу так, словно вы
и не использовали при этом механизмов перекрывающегося ввода/вывода. Ес-
ли функция вернула ненулевое значение, значит, операция ввода/вывода ус-
пешно завершена, а передача данных произошла фактически точно так же, как
если бы вы не использовали перекрывающегося ввода/вывода.
Особенности асинхронного ввода/вывода проявляются в случае, если
функция возвращает значение FALSE. Нулевое значение, возвращенное функ-
цией ввода/вывода, означает, что либо процедура ввода/вывода находится
в стадии выполнения, либо произошла какая-либо ошибка. Чтобы уточнить,
65