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

Отображение файлов в память
Для работы с файлом динамической подкачки страниц виртуальной памяти в Windows 32 используется механизм отображения файлов в адресное пространство программы. Соответствующие функции API доступны любой программе и могут применяться к любому файлу (кстати, таким способом загружается в адресное пространство процесса исполняемый файл). В результате отображения программа может работать с файловыми данными как с данными, размещенными в динамической памяти. Такая возможность не только в большинстве случаев повышает скорость работы с данными, но и предоставляет программисту уникальные средства обработки сразу всех записей файла. Например, он может единственным оператором проверить входит ли заданный образец поиска в любую строку текстового файла. Отображение файла осуществляется в три приема.
== Создание/открытие файла ==
Вначале файл создается обращением к функции
function FileCreate(FileName: String): Integer;
или открывается с помощью
function FileOpen(const FileName: String; Mode: LongWord): Integer;
В обеих функциях FileName - имя файла, возможно, с маршрутом доступа. Параметр Mode определяет режим доступа к файлу и может принимать одно из следующих значений:
* fmOpenRead - только чтение;
* fmOpenWrite - только Запись;
* fmOpenReadWrite - чтение и запись.
C помощью операции or эти константы можно комбинировать с одной из следующих регулирующих совместный доступ к файлу нескольких Программ:
* fmShareExclusive - совместный доступ Запрещен;
* fmShareDenyWrite - Другим Программам запрещается запись;
* fmShareDenyRead - другим программам запрещается чтение;
* fmSchareDenyNone - совместный доступ неограничен.
Обе функции возвращают дескриптор созданного (открытого) файла или 0, если операция оказалась неуспешной.
== Создание объекта отображения ==
На втором этапе создается объект отображения в память. Для этого используется такая функция:
function CreateFileMapping(hFile: THandle; IpFileMappingAttributes: PSecurityAttributes;
 flProtect, dwMaximumSizeHigh, dwMaximumSizeLow: DWord; IpName: PChar): THandle;
* hFile - дескриптор файла;
* ipFileMappingAttributes - указатель на структуру, в которой определяется, может ли создаваемый объект порождать дочерние объекты (обычно не может - nil);
* flProtect - определяет тип защиты, применяемый к окну отображения файла (см.ниже);
* dwMaximumSizeHigh, dwMaximumSizeLow - соответственно Старшие и младшие 32 разряда размера файла; если вы будете отображать файлы длинной до 4 ГбаЙТ, поместите В dwMaximumSizeHigh 0, а В dwMaximumSizeLow - длину файла; если оба параметра равны 0, размер окна отображения равен размеру файла;
* ipName - имя объекта отображения или nil.
Параметр flProtect задает тип защиты, применяемый к окну просмотра файла, и может иметь одно из следующих значений:
* PAGE_READONLY - файл можно только читать (файл должен быть создан или открыт В режиме fmOpenRead);
* PAGE_READWRITE - файл можно читать и записывать в него новые данные (файл открывается в режиме fmOpenReadWrite);
* PAGE_WRITECOPY - файл открыт для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти (отображенные файлы могут разделяться программами, в этом режиме каждая программа сохраняет изменения в отдельной области памяти или участке файла подкачки); файл открывается В режиме fmOpenReadWrite или fmOpenWrite; этот тип защиты нельзя использовать в Windows 95/98.
С помощью операции or к параметру flProtect можно присоединить такие атрибуты:
* sec_commit - выделяет для отображения физическую память или участок файла подкачки;
* sec_image - информация об атрибутах отображения берется из образа файла;
* sec_nocashe - отображаемые данные не кэшируются и записываются непосредственно на диск;
* sec_reserve - резервируются страницы раздела без выделения физической памяти.
Функция возвращает дескриптор объекта отображения или 0, если обращение было неудачным.
== Создание окна просмотра ==
Наконец, на третьем этапе создается окно просмотра, т. е. собственно отображение данных в адресное пространство программы:
function MapViewOfFile(hFileMappingObject: THandle; dwDesiresAccess: DWord;
 dwFileOffsetHigh, dwFileIffsetLow, dwNumberOfBytesToMap: DWord): Pointer;
* hFileMappingObject - дескриптор объекта отображения;
* dwDesiresAccess - определяет способ доступа к данным и может иметь одно из следующих значений:
** file_map_write - разрешает чтение и запись, При ЭТОМ В функции CreateFileMapping должен использоваться атрибут page_readwrite;
** file_map_read - разрешает только чтение, в функции CreateFileMapping должен использоваться атрибут PAGE_READONLY или PAGE_READWRITE; FILE_MAP_ALL_ACCESS - то же, что и file_map_write;
** file_map_copy - данные доступны для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти; в функции CreateFileMapping должен использоваться атрибут PAGE_WRITECOPY;
* dwFileOffsetHigh, dwFileIffsetLow - определяют соответственно старшие и младшие разряды смещения от начала файла, начиная с которого осуществляется отображение;
* dwNumberOfBytesToMap - определяет длину окна отображения (0 - длина равна длине файла).
Функция возвращает указатель на первый байт отображенных данных или nil, если обращение к функции оказалось неуспешным.
== Освобождение ресурсов отображения ==
После использования отображенных данных ресурсы окна отображения нужно освободить функцией
function UnMapViewOfFile(IpBaseAddress: Pointer): BOOL;
единственный параметр обращения к которой должен содержать адрес первого отображенного байта, т. е. адрес, возвращаемый функцией MapViewOfFile. Закрытие объекта отображения и самого файла осуществляется обращением к функции
function CloseHandle(hObject: THandle)
== Пример использования ==
Программа создает дисковый файл, состоящий из 100000 случайных вещественных чисел (длину файла можно выбрать другой, если изменить значение редактора длина массива). Файл с именем test.dat создается путем отображения файла в память (кнопка память) и традиционным способом (кнопка Файл). В обоих случаях показывается время счета (процессор 400 МГц, память 64 Мбайт). Чем больше частота и память, тем больше будет разница во времени.
unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Spin;
type
 TFormI = class (TForm)
 btMem: TButton;
 btFile: TButton;
 se: TSpinEdit;
 Labell: TLabel;
 pb: TProgressBar;
 Label2: TLabel;
 IbMem: TLabel;
 IbFile: TLabel;
 procedure btMemClick(Sender: TObject);
 procedure btFileClick(Sender: TObject);
 private
 { Private declarations }
 public
 { Public declarations }
 end;
var
 Form1: TForm1;
implementation
{$R *.DFM}
// Создание файла методом его отображения
procedure TForm1.btMemClick(Sender: TObject);
type
 PReal = ^Real;
var
 HFile, HMap: THandle;
 AdrBase, AdrReal: PReal;
 k: Integer;
 FSize: Cardinal;
 BegTime: TDateTime;
begin
 BegTime := Time; // Засекаем время пуска
 // Готовим ProgressBar:
 pb.Max := se.Value;
 pb.Position := 0;
 pb.Show;
 FSize := se.Value * SizeOf(Real); // Длина файла
 HFile := FileCreate('test.dat'); // Создаем файл
 if HFile = 0 then // Ошибка: возбуждаем исключение
 raise Exception.Create('Ошибка создания файла');
 try
 // Отображаем файл в память
 HMap := CreateFileMapping(HFile, NIL, PAGE_READWRITE, 0, FSize, NIL);
 if HMap = 0 then // Ошибка: возбуждаем исключение
 raise Exception.Create('Ошибка отображения файла');
 try
 // Создаем окно просмотра:
 AdrBase := MapViewOfFile(HMap, FILE_MAP_WRITE, О, О, FSize) ;
 if AdrBase = NIL then // Ошибка: возбуждаем исключение
 raise Exception.Create('Невозможно просмотреть файл');
 // Сохраняем начальный адрес для правильной ликвидации окна просмотра:
 AdrReal := AdrBase;
 for k := 1 to se.Value do
 begin
 AdrReal^ := Random; // Помещаем в файл новое число
 // Перед наращиванием текущего адреса необходимо
 // привести его к типу Integer или Cardinal:
 AdrReal := Pointer(Integer(AdrReal) + SizeOf(Real));
 IbMem.Caption := IntToStr(k);
 pb.Position := k;
 Application.ProcessMessages;
 end;
 // Освобождаем окно просмотра:
 UnmapViewOfFile(AdrBase)
 finally
 // Освобождаем отображение
 CloseHandle(HMap);
 end;
 finally
 // Закрываем файл
 CloseHandle(HFile);
 end;
 // Сообщаем время счета
 pb.Hide;
 IbMem.Caption := TimeToStr(Time - BegTime);
end;
// Создание файла обычным методом var
procedure TFormI.btFileClick(Sender: TObject) ;
 F: file of Real;
 k: Integer;
 BegTime: TDateTime;
 R: Real; // Буферная переменная для обращение к Write
begin
 BegTime := Time; // Засекаем начальное время счета
 // Готовим ProgressBar:
 pb.Max := se.Value;
 pb.Position := 0;
 pb.Show;
 // Создаем файл:
 AssignFile(F, 'test.dat');
 Rewrite(F);
 for k := 1 to se.Value do
 begin
 R := Random; // Параметрами обращения к Write
 Write(F, R); // могут быть только переменные
 IbFile.Caption := IntToStr(k);
 pb.Position := k;
 Application.ProcessMessages;
 end;
 CloseFile(F) ;
 pb.Hide;
 IbFile.Caption := TimeToStr(Time - BegTime)
end;
end.
ID: 03123
ID: 03134
Category:Файловая система