Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






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






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

Создание проекции файла производится в три этапа:

1. создание объекта ядра типа файл;

2. создание объекта ядра проекция файла;

3. проецирование части файла в адресное пространство процесса.

Для создания объекта файл необходимо воспользоваться функцией CreateFile, также как и при обычном открытии файла:

HANDLE CreateFile(

LPCTSTR lpFileName, // file name

DWORD dwDesiredAccess, // access mode

DWORD dwShareMode, // share mode

LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD

DWORD dwCreationDisposition, // how to create

DWORD dwFlagsAndAttributes, // file attributes

HANDLE hTemplateFile // handle to template file

);

Имя файла передается в параметре lpFileName. Файл должен быть открыт с правами доступа (dwDesiredAccess), соответствующими правам доступа, которые будут в дальнейшем использоваться для доступа к памяти. Параметр dwShareMode позволяет задать режим доступа к файлу для других процессов. Рекомендуется использовать эксклюзивный доступ, передав значение 0. Параметр lpSecurityAttributes позволяет задать обычные для объектов ядра права доступа к объекту. dwCreationDisposition определяет режим открытия файла. Для открытия существующего файла он должен быть равен OPEN_EXISTING. При создании проекции файла параметры dwFlagsAndAttributes и hTemplateFile можно задать равными 0 и NULL соответственно.

В случае ошибки функция CreateFile возвращает значение INVALID_HANDLE_VALUE.

Следующий этап это создание объекта ядра проекция файла. Это можно сделать с помощью функции CreateFileMapping:

HANDLE CreateFileMapping(

HANDLE hFile, // handle to file

LPSECURITY_ATTRIBUTES lpAttributes, // security

DWORD flProtect, // protection

DWORD dwMaximumSizeHigh, // high-order DWORD of size

DWORD dwMaximumSizeLow, // low-order DWORD of size

LPCTSTR lpName // object name

);

Прежде всего, необходимо передать ей в параметре hFile дескриптор открытого файла, который будет отображаться в память. Параметр lpAttributes определяет права доступа к создаваемому объекту ядра. Флаги dwProtect определяют права доступа к отображению памяти и могут принимать значения PAGE_READONLY, PAGE_READWRITE и PAGE_WRITECOPY.

Максимальные размеры проецируемого файла задаются параметрами dwMaximumSizeHigh и dwMaximumSizeLow. Поскольку максимальный размер файла в Windows превышает 232, то это значение разбивается на два 32-х битных значения. Если передать в обеих частях 0, то для создания проекции будет использован текущий размер файла. Однако это может привести к ошибке, если в этот момент сам файл также имеет нулевой размер.

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

Параметр lpName позволяет задать имя для объекта проекция файла.

Функция CreateFileMapping возвращает дескриптор созданного объекта ядра, или значение NULL в случае ошибки.

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

HANDLE OpenFileMapping(

DWORD dwDesiredAccess, // access mode

BOOL bInheritHandle, // inherit flag

LPCTSTR lpName // object name

);

Размеры файла в Windows превосходят размер адресного пространства, поэтому, вообще говоря, мы не можем проецировать большие файлы целиком в адресное пространство нашего процесса. Поэтому, после того как мы создали или открыли объект проекция файла, нам необходимо указать, какую часть файла мы хотим отобразить в память. Сделать это можно с помощью вызова MapViewOfFile:

LPVOID MapViewOfFile(

HANDLE hFileMappingObject, // handle to file-mapping object

DWORD dwDesiredAccess, // access mode

DWORD dwFileOffsetHigh, // high-order DWORD of offset

DWORD dwFileOffsetLow, // low-order DWORD of offset

SIZE_T dwNumberOfBytesToMap // number of bytes to map

);

В параметре hFileMappingObject передается дескриптор проекции файла. Флаги dwDesiredAccess определяют запрашиваемые права доступа к проекции файла и, соответственно, к отображенным страницам памяти. Они могут принимать значения FILE_MAP_WRITE, FILE_MAP_READ, FILE_MAP_ALL_ACCESS и FILE_MAP_COPY. Необходимо заметить, что режим FILE_MAP_WRITE подразумевает кроме записи также и чтение и таким образом ничем не отличается от FILE_MAP_ALL_ACCESS.

Параметры dwFileOffsetHigh и dwFileOffsetLow определяют 64-х битное смещение проецируемой области от начала файла. Это смещение должно быть кратно гранулярности выделения памяти в системе, которую можно узнать с помощью функции GetSystemInfo.

Размер области задается одним 32-х битным числом dwNumberOfBytesToMap. Если передать в этом параметре 0, то будет отображен весь файл.

Функция возвращает адрес отображенного фрагмента или NULL в случае ошибки. Существует также функция MapViewOfFileEx, которая позволяет задать базовый адрес, по которому желательно разместить проецируемую память.

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

Отображенную в адресное пространство память можно освободить вызовом функции UnmapViewOfFile, передав ей начальный адрес отображенной памяти:

BOOL UnmapViewOfFile(

LPCVOID lpBaseAddress // starting address

);

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

BOOL FlushViewOfFile(

LPCVOID lpBaseAddress, // starting address

SIZE_T dwNumberOfBytesToFlush // number of bytes in range

);

Мы можем задать начальный адрес синхронизуемой области в параметре lpBaseAddress и ее размер в dwNumberOfBytesToFlush. Если задать размер равный 0, то будет сброшена вся память проекции, начиная с базового адреса и до конца.

При завершении работы с проекциями файлов не забудьте закрыть объекты ядра проекция файла и файл, используя функцию CloseHandle.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.