Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 2.DOC
Скачиваний:
91
Добавлен:
10.05.2014
Размер:
827.9 Кб
Скачать

Файлы, проецируемые в память

Как известно, процессор не может работать с содержимым файла, находящегося на диске, – для обращения к какому-либо участку файла этот участок необходимо сначала прочитать в память. Если же требуется не просто обработать данные из файла, а модифицировать его содержимое, то к операции чтения файла добавляется еще и операция его записи. Поэтому стандартная для 16-разрядных приложений процедура работы с дисковым файлом (в наиболее полном виде, когда требуется модификация файла) включает по меньшей мере четыре этапа:

  • открытие файла на диске;

  • чтение требуемого участка файла в созданную заранее программную переменную;

  • модификация этой программной переменной по заданному алгоритму;

  • запись модифицированной переменной на то же место в файле на диске.

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

Значительно более эффективным было бы чтение всегофайла в оперативную память. В этом случае потребуется только одна операция физического чтения в начале сеанса работы и одна операция физической записи в конце сеанса. Однако такая методика возможна только при работе с файлами относительно небольшого размера.

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

Процедура создания и использования проекции файла (рис. 6.1) распадается на несколько этапов:

  • открытие (или, возможно, создание) файла обычным образом с помощью функции CreateFile();

  • создание в физической памяти объекта “проекция файла” с помощью функции CreateFileMapping();

  • выделение в линейном пространстве области адресов для проекции файла и отображение этой области на проекцию файла в физической памяти с помощью функции MapViewOfFile(), которая возвращает указатель на выделенную область;

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

Рис. 6.1. Процесс проецирования файла в память

Рассмотрим содержательную часть программы, осуществляющей проецирование файла в память и работу с его проекцией. Будем считать, что файл с именем 1.datсостоит из 1000 чисел типаint(и занимает, следовательно, на диске пространство 4000 байт).

/*Операция открытия существующего файла*/

hFile=CreateFile("1.dat",GENERIC_READ,

0,NULL,OPEN_EXISTING,0,NULL);

/*Создание в памяти объекта "проекция файла"*/

HANDLE hMem=CreateFileMapping

(hFile,NULL,PAGE_READONLY,0,0,NULL);

/*Отображение линейных адресов на проекцию файла */

int* ptr = (int*)MapViewOfFile(hMem,FILE_MAP_READ,0,0,0);

/*Чтение участков файла*/

intx=ptr[0];//Чтение первого данного из файла

inty=ptr[999];//Чтение последнего данного из файла

В приведенном примере файл был открыт только для чтения (параметр GENERIC_READфункцииCreateFile()). Соответственно, такой же атрибут получила проекция файла в физической памяти (параметрPAGE_READONLY), а также и выделенная область линейных адресов (параметрFILE_MAP_READ). Если в проецируемый файл предполагается выполнять запись новых данных, тогда для соответствующих параметров вызываемых функций следует указать значенияGENERIC_READ|GENERIC_WRITE,PAGE_READWRITEиFILE_MAP_ALL_ACCESS.

Файл с данными может состоять из данных любого типа. Поэтому функция MapViewOfFile(), которая должна выполнять свою работу для любых типов данных, возвращает в соответствии со своим прототипом обобщенный указатель типаLPVOID. При использовании возвращаемого этой функцией значения его необходимо преобразовать в указатель на конкретный тип данных, содержащихся в файле. В нашем случае файл заполнен числами типаint, и возвращаемое значение явным образом преобразуется в типint*. Если бы файл был заполнен, например, байтовыми переменными типаcharилиBYTE, то и указатель на проекцию файла следовало получить такого же типа:

BYTE* ptr = (BYTE*)MapViewOfFile(...);

Четвертый и пятый параметры функции CreateFile­Map­ping()позволяют задать размер проекции файла. Указание в качестве параметров нулевых значений заставляет Windows спроеци­ровать весь файл.

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