Асинхронный файловый ввод/вывод в операционной системе WINDOWS, страница 20

Если вы обращаетесь к функции ReadFile или GetOverlappedResult и эта функция возвращает значение FALSE, значит, либо операция чтения не завершена, либо встречен конец файла, либо произошла какая-либо другая ошибка. Чтобы узнать точно, следует обратиться к функции GetLastError. В случае если во время выполнения операции чтения был встречен конец файла, вызов GetLastError вернет значение ERROR_HANDLE_EOF.

Использование функций ReadFileEx и WriteFileEx

В некоторых ситуациях при асинхронном вводе/выводе вместо функций ReadFile и WriteFile удобнее использовать функции ReadFileEx и WriteFileEx. Эти две функции нельзя использовать для осуществления синхронного ввода/вывода,

В отличие от вызовов ReadFile и WriteFile, вызовы ReadFileEx и WriteFileEx используют дополнительный аргумент. Этот аргумент содержит указатель на функцию, которая будет автоматически вызвана в момент завершения операции ввода/вывода.

К сожалению, существует особенность, ограничивающая использование вызовов ReadFileEx и WriteFileEx. Дело в том, что для вызова функции завершения ввода/вывода используется АРС (см. лаб.работу про ПОТОКИ). Таким образом, функция завершения сможет начать работу только тогда, когда поток, обратившийся к ReadFilеЕх или WriteFileEx, находится в «настороженном» состоянии. Другими словами программа не сможет отреагировать на завершение ввода/вывода до тех пор, пока не будет выполнено обращение к вызовам SleepEx, WaitForSingleObjectEx или WaitForMultipleObjectsEx, которые переводят текущий поток в «настороженное» состояние.

Использование портов завершения

За завершением ввода/вывода можно следить при помощи портов завершения. Чтобы создать порт завершения, вы должны открыть файл для перекрывающегося ввода/вывода, а затем обратиться к вызову CreateIoCompletionPort и передать ему в качестве аргументов дескриптор файла и 32-битное число, называемое ключом (ключ может иметь любое удобное для вас значение).

Когда выполнение операции ввода/вывода, связанной с указанным вами дескриптором файла, будет завершено, в порт завершения будет послано уведомление о завершении. Порт завершения представляет собой очередь, в которой может содержаться несколько таких уведомлений. Любой поток, обращающийся к порту при помощи вызова GetQueuedCompletionStatus, получит следующее доступное для чтения уведомление.

Порты завершения удобнее всего использовать при разработке приложений, в которых фиксированное количество потоков обслуживает весь ввод/вывод (например, Web-сервер с фиксированным количеством программных потоков). Простой пример использования портов завершения приведен в листинге 3.

Отображение файлов на оперативную память

Механизм отображения файлов на адресное пространство в памяти является новым удобным способом работы с файлами в Windows, Чтобы воспользоваться этим механизмом, откройте файл при помощи вызова CreateFile, а затем передайте дескриптор файла вызову CreateFileMapping. При этом будет создан объект отображения файла на память, После этого обратитесь к функции MapViewOfFile, которая возвратит вам указатель на содержимое файла. Этот указатель является обычным указателем на ячейку оперативной памяти. Его можно использовать точно так же, как вы используете любой другой указатель. Таким образом, вы работаете с файлом так, как будто это не файл, а участок оперативной памяти.

Когда работа с файлом завершена, необходимо обратиться к вызову UnmapViewOfFile, после чего дважды вызвать CloseHandle, чтобы закрыть объект отображения файла и закрыть дескриптор файла. Пример использования отображения файла приведен в листинге 4.

Механизм, отображения файлов на память очень удобно использовать для чтения их содержимого, однако он несколько менее удобен в случае, если требуется выполнить запись в файл. Дело в том, что если вы намерены дописать данные в конец файла, то при его отображении на память вы должны указать результирующий размер этого файла.