Программирование для Windows NT (том 2)

       

Создание отображения файла


Рассмотрим процедуру создания отображения файла на память.

Прежде всего, приложение должно открыть файл при помощи функции CreateFile, известной вам из предыдущего тома “Библиоткеи системного программиста”. Ниже мы привели прототип этой функции:

HANDLE CreateFile(

  LPCTSTR lpFileName,              // адрес строки имени файла

  DWORD   dwDesiredAccess,         // режим доступа

  DWORD   dwShareMode,// режим совместного использования файла

  LPSECURITY_ATTRIBUTES lpSecurityAttributes, // дескриптор

                                              // защиты

  DWORD  dwCreationDistribution,   // параметры создания

  DWORD  dwFlagsAndAttributes,     // атрибуты файла

  HANDLE hTemplateFile);   // идентификатор файла с атрибутами

Через параметр lpFileName вы, как обычно, должны передать этой функции адрес текстовой строки, содержащей путь к открываемому файлу.

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

Не забудьте также про параметр dwShareMode. Если файл будет использоваться одновременно несколькими процессами, через этот параметр необходимо передать режимы совместного использования файла: FILE_SHARE_READ или FILE_SHARE_WRITE.

Остальные параметры этой функции мы уже описали в предыдущем томе.

В случае успешного завершения, функция CreateFile возвращает идентификатор открытого файла. При ошибке возвращается значение INVALID_HANDLE_VALUE. Здесь все как обычно, пока никакого отображения еще не выполняется.



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

HANDLE CreateFileMapping(

  HANDLE hFile,           // идентификатор отображаемого файла


  LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // дескриптор

                                                 // защиты

  DWORD flProtect,         // защита для отображаемого файла

  DWORD dwMaximumSizeHigh, // размер файла (старшее слово)

  DWORD dwMaximumSizeLow,  // размер файла (младшее слово)

  LPCTSTR lpName);         // имя отображенного файла

Через параметр hFile этой функции нужно передать идентификатор файла, для которого будет выполняться отображение в память, или значение 0xFFFFFFFF. В первом случае функция CreateFileMapping отобразит заданный файл в память, а во втором - создаст отображение с использованием файла виртуальной памяти. Как мы увидим позже, отображение с использованием файла виртуальной памяти удобно для организации передачи данных между процессами.

Обратим ваше внимание на одну потенциальную опасность, связанную с использованием в паре функций CreateFile и CreateFileMapping. Если функция CreateFile завершится с ошибкой и эта ошибка не будет обработана приложением, функция CreateFileMapping получит через параметр hFile значение INVALID_HANDLE_VALUE, численно равное 0xFFFFFFFF. В этом случае она сделает совсем не то, что предполагал разработчик приложения: вместо того чтобы выполнить отображение файла в память, функция создаст отображение с использованием файла виртуальной памяти.

Параметр lpFileMappingAttributes задает адрес дескриптора защиты. В большинстве случаев для этого параметра вы можете указать значение NULL.

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

Значение

Описание

PAGE_READONLY

К выделенной области памяти предоставляется доступ только для чтения. При создании или открывании файла необходимо указать флаг GENERIC_READ

PAGE_READWRITE

К выделенной области памяти предоставляется доступ для чтения и записи. При создании или открывании файла необходимо указать флаги GENERIC_READ и GENERIC_WRITE

PAGE_WRITECOPY

К выделенной области памяти предоставляется доступ для копирования при записи. При создании или открывании файла необходимо указать флаги GENERIC_READ и GENERIC_WRITE. Режим копирования при записи будет описан позже в главе, посвященной обмену данными между процессами

<


Эти значения можно комбинировать при помощи логической операции ИЛИ со следующими атрибутами:

Атрибут

Описание

SEC_COMMIT

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

SEC_IMAGE

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

SEC_NOCACHE

Отмена кэширования для всех страниц отображаемой области памяти. Должен использоваться вместе с атрибутами SEC_RESERVE или SEC_COMMIT

SEC_RESERVE

Если указан этот атрибут, вместо выделения выполняется резервирование страниц виртуальной памяти. Зарезервированные таким образом страницы можно будет получить в пользование при помощи функции VirtualAlloc. Атрибут SEC_RESERVE можно указывать только в том случае, если в качестве параметра hFile функции CreateFileMapping передается значение 0xFFFFFFFF

С помощью параметров dwMaximumSizeHigh и dwMaximumSizeLow необходимо  указать функции CreateFileMapping 64-разрядный размер файла. Параметр dwMaximumSizeHigh должен содержать старшее 32-разрядное слово размера, а параметр dwMaximumSizeLow - малдшее 32-разрядное слово размера. Для небольших файлов, длина которых укладывается в 32 разряда, нужно указывать нулевое значение параметра dwMaximumSizeHigh.

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

Через параметр lpName можно указать имя отображения, которое будет доступно всем работающим одновременно приложениям. Имя должно представлять собой текстовую строку, закрытую двоичным нулем и не содержащую символов “\”.

Если отображение будет использоваться только одним процессом, вы можете не задавать для него имя. В этом случае значение параметра lpName следует указать как NULL.

В случае успешного завершения функция CreateFileMapping возвращает идентификатор созданного отображения. При ошибке возвращается значение NULL.

Так как имя отображения глобально, возможно возникновение ситуации, когда процесс пытается создать отображение с уже существующим именем. В этом случае функция CreateFileMapping возвращает идентификатор существующего отображения. Такую ситуацию можно определить с помощью функции GetLastError, вызвав ее сразу после функции CreateFileMapping. Функция GetLastError при этом вернет значение ERROR_ALREADY_EXISTS.


Содержание раздела