Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаба10.doc
Скачиваний:
6
Добавлен:
12.11.2019
Размер:
195.58 Кб
Скачать

3.3. Проецирование файловых данных на адресное пространство процесса

Когда объект «проекция файла» создан, нужно, чтобы система, зарезервировав регион адресного пространства под данные файла, передала их как физическую память, отображенную на регион. Это делает функция MapViewOfFile:

PVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap);

Параметр hFileMappingObject идентифицирует описатель объекта «проекция файла», возвращаемый предшествующим вызовом либо CreateFileMapping, либо OpenFileMapping. Параметр dwDesiredAccess идентифицирует вид доступа к данным. Bce правильно придется опять указывать, как именно планируется обращаться к файловым данным. Можно задать одно из четырех значений, описанных в следующей таблице.

Таблица 3.4. Виды доступа к данным проекции файла

Значение

Описание

FILE_MAP_WRITE

Файловые данные можно считывать и записывать, при этом функции CreateFileMapping передается атрибут PAGE_READWRITE

FILE MAP_READ

Файловые данные можно только считывать, необходимо было вызвать CreateFileMapping с любым из следующих атрибутов PAGE_READONLY, PAGE_READWRITE или PAGE_WRITECOPY

FILE_MAP_ALL_ACCESS

То же, что и FILE_MAP_WRITE

FILE_MAP_COPY

Файловые данные можно считывать и записывать, но запись приводит к созданию закрытой копии страницы, необходимо было вызвать CrealeFileMapping с любым из следующих атрибутов PAGE_READONIY, PAGE_READWRITE или РАСЕ_WRITECOPY (Windows 98 требует вызывать CreateFileMapping с атрибутом PACE_WRITECOPY)

Остальные три параметра относятся к резервированию региона адресного пространства и к отображению на него физической памяти. При этом необязательно проецировать на адресное пространство весь файл сразу. Напротив, можно спроецировать лишь малую его часть, которая в таком случае называется представлением (view).

Проецируя на адресное пространство процесса представление файла, нужно сделать две вещи. Во-первых, сообщить системе, какой байт файла данных считать в представлении первым. Для этого предназначены параметры dwFileOffsetHigh и dwFileOffsetLow. Поскольку Windows поддерживает файлы длиной до 16 экзабайтов, приходится определять смещение в файле как 64 разрядное число, старшие 32 бита передаются в параметре dwFileOffsetHigh, а младшие 32 бита — в параметре dwFileOffsetLow.

Смещение в файле должно быть кратно гранулярности выделения памяти в данной системе. В настоящее время во всех реализациях Windows она составляет 64 Кб. Во-вторых, потребуется указать размер представления, т.e. сколько байтов файла данных должно быть спроецировано на адресное пространство. Это равносильно тому, как если задать размер региона, резервируемого в адресном пространстве. Размер указывается в параметре dwNumberOfBytesToMap. Если этот параметр равен 0, система попытается спроецировать представление, начиная с указанного смещения и до конца файла

Если при вызове MapViewOfFile указан флаг FILE_MAP_COPY, система передает физическую память из страничного файла. Размер передаваемого пространства определяется параметром dwNumberOfBytesToMap. Пока идет только считывание данных из представления файла, страницы, переданные из страничного файла, не используются. Но стоит какому-нибудь потоку в процессе совершить попытку записи по адресу, попадающему в границы представления файла, как система тут же берет из страничного файла одну из переданных страниц, копирует на нее исходные данные и проецирует ее на адресное пространство процесса. Так что с этого момента потоки начинают обращаться к локальной копии данных и теряют доступ к исходным данным.

Создав копию исходной страницы, система меняет ее атрибут защиты с PAGE_WRI TECOPY на PAGE_READWRITE.

Далее приведен пример кода, иллюстрирующий данный момент.

Пример:

// открываем файл, который мы собираемся спроецировать HANDLE hFile = CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

// создаем для файла объект "проекция файла" HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL);

// Проецируем представление файла с атрибутом "копирование при записи"; // система передаст столько физической памяти из страничного файла, // сколько нужно для размещения всего файла. Первоначально все страницы // в представлении получат атрибут PAGE_WRITECOPY. PBYTE pbFile = (PBYTE) MapViewOfFile(hFileMapping, FILE_MAP_COPY, 0, 0, 0);

// считываем байт из представления файла BYTE bSomeByte = pbFile[0];

// при чтении система не трогает страницы, переданные из страничного файла; // страница сохраняет свой атрибут PAGE_WRITECOPY

// записываем байт в представление файла pbFile[0] = 0;

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

// записываем еще один байт в представление файла pbFile[1] = 0;

// поскольку теперь байт располагается на странице с атрибутом PAGE_RFADWRITE, // система просто записывает его на эту страницу (она связана со страничным //файлом)

// закончив работу с представлением проецируемого файла, прекращаем проецирование; // функция UnmapViewOfFile обсуждается в следующем разделе UnmapViewOfFile(pbFile);

// вся физическая память, взятая из страничного файла, возвращается системе; // все, что было записано на эти страницы, теряется

// закрытие объектов ядра CloseHandle(hFileMapping); CloseHandle(hFile);

Windows 98 сначала передаст проецируемому файлу физическую память из страничного файла. Однако запись модифицированных страниц в страничный файл происходит только при необходимости.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]