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

WriteFile работает аналогичным образом с тем исключением, что системный сервис NtWriteFile генерирует IRP типа IRP_MJ_WRITE, a FSD вызывает не CcCopyRead, a CcCopyWrite. Последняя, как и CcCopyRead, проверяет, спроецированы ли на кэш части записываемого файла, и копирует в кэш содержимое буфера, переданного в WriteFile.

Если файловые данные уже хранятся в системном рабочем наборе, вышеописанный сценарий немного меняется. Если файловые данные находятся в кэше, CcCopyRead не вызывает ошибки страниц. Кроме того, в определенных обстоятельствах NtReadFile и NtWriteFile - вместо того чтобы немедленно создать IRP и послать его FSD – вызывают в FSD точку входа для быстрого ввода-вывода. Вот некоторые из этих обстоятельств: считываемая часть файла должна находиться в первых 4 Гб файла, в файле не должно быть блокировок, а считываемая или записываемая часть файла не должна выходить за пределы его текущей длины.

B большинстве FSD точки быстрого ввода-вывода вызывают в диспетчере кэша функции CcFastCopyRead и CcFastCopyWrite для чтения и записи. Эти варианты стандартных процедур копирования требуют, чтобы перед копированием файловые данные были спроецированы на кэш файловой системы. Если это условие не выполнено, CcFastCopyRead и CcFastCopyWrite сообщают о невозможности быстрого ввода-вывода; тогда функции NtReadFile и NtWriteFile возвращаются к созданию IRP (Более полное описание быстрого ввода-вывода см. в разделе «Быстрый ввод-вывод» главы 11.)



18 из 207