Подкачку - под контроль!
🕛 25.03.2008, 12:23
Вообще, в 32-разрядной Windows под памятью понимают не только оперативку, но и память, резервируемую операционной системой на жёстком диске (файл подкачки). Код и данные отображаются на жесткий диск с помощью страничной системы (paging system) подкачки. Страничная система использует для отображения страничный файл (pagefile.sys в Windows NT и, если мне не изменяет память, win386.swp в Windows 95/98). Нужный кусок виртуальной памяти переносится из страничного файла в ОЗУ и, таким образом, становится доступным.А если таким макаром создовать любой другой файл и сделать его куском адрессного пространства? В Win32 это возможно. Для выделения фрагмента памяти должен быть создан специальный системный объект Win32, называемый отображаемым файлом. Посредством этого объекта просиходит соотношения файла, находящегося на жестком диске, с памятью, адресуемой процессами.
Приложения могут открывать отображаемый файл и получать доступ к данным этого объекта. Т.е. данные, помещённые в страничный файл, могут быть доступны другим приложениям, если они открыли и используют тот же отображаемый файл.
Итак, значит у нас есть два варианта - либо создать свой собственный файл подкачки, либо использовать уже существующий, например, файл подкачки вЕнды. В каких-то случаях будет удобнее и практичнее создать свой страничный файл, но в каких-то лучше использовать уже готовый. Разницей в реализации этих способов будет лишь изменение параметра одной из используемых функций.
Теперь давай разбираться с функциями, которые дают нам возможность работы с файлами подкачки. Это, естественно, функции WinAPI и их три:
1.CreateFileMapping
2.MapViewOfFile
3.UnMapViewOfFile
Отображаемый файл создается операционной системой при вызове функции CreateFileMapping. Этот объект поддерживает соответствие между содержимым файла и адресным пространством процесса, использующего этот файл. Функция CreateFiieMapping(hFile: THandle; IpFileMappingAttributes: PSecurityAttributes; flProtect, dwMaximumSizeHigh, dwMaximumSizeLow: DWORD; IpName: PChar): THandle; имеет шесть параметров:
hFile: THandle - он должен соответствовать хендлу уже открытого файла.
IpFileMappingAttributes: PSecurityAttributes - указатель на запись типа TSecurityAttributes. При отсутствии требований к защите данных в Windows NT этот параметр всегда равен nil.
flProtect: DWORD - определяет атрибут защиты. Т.к. мы планируем совместное (ОС и прога) использование данных, то нам будет достаточно значения PAGE_READWRITE.
dwMaximumSizeHigh, dwMaximumSizeLow: DWORD - Когда выполняется функция CreateFiieMapping, то, проще говоря, эти значения объединяются в одно 64-разрядное число, равное объему памяти, выделяемой объекту файлового отображения из страничного файла операционной системы. Мы хотим отобразить весь файл, значит четвертый и пятый параметры должны быть равны нулю.
IpName: PChar - имя объекта файлового отображения.
Функция CreateFileMapping возвращает значение типа THandle. В случае успешного завершения возвращаемое функцией значение равно дескриптору созданного объекта файлового отображения. В случае возникновения какой-либо ошибки возвращаемое значение будет равно 0.
Теперь надо спроецировать данные файла в адресное пространство нашего процесса. Для этого нужно заюзать функцию function MapViewOfFile(hFileMappingObject: THandle; dwDesiredAccess: DWORD; dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap: DWORD):Pointer; Она имеет пять параметров:
hFileMappingObject: THandle - этим значением должен быть дескриптор созданного объекта файлового отображения, который возвращает функция createFileMapping.
dwDesiredAccess: DWORD - этот параметр определяет режим доступа к файлу. Может быть равным: FILE_MAP_WRITE, FILE_MAP_READ или FILE_MAP_ALL_ACCESS.
dwFileOffsetHigh, dwFileOffsetLow: DWORD - смещение отображаемого участка относительно начала файла в байтах. Ставь их равными нулю (это потому, что последний параметр так же будет равен нулю, см. ниже).
dwNumberOfBytesToMap: DWORD - используется для определения (в байтах) количества данных файла подкачки, которые надо сделать доступными для нас. Если выставить этот параметр в ноль, то в процессе автоматически отоброзятся все данные, выделенные перед этим функцией
CreateFileMapping.
Если функция MapViewOfFile отработала успешно, то она вернет начальный адрес данных объекта файлового отображения.
Теперь давай попробуем накотать какой-нить пример:
var
hMappedFile: THandle;
pSharedBuf: PChar;
begin
//создаём отображаемый файл
hMappedFile :=CreateFileMapping(FHandle, nil, PAGE_READWRITE, 0, 0, 'SharedBlock');
if (hMappedFile = 0) then
ShowMessage('Mapping error!')
else
begin
//проецируем данные файла в адресное пространство
pSharedBuf :=MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0) ;
if (pSharedBuf = nil) then
ShowMessage ('MapView error');
end;
end;
После того как получен указатель pSharedBuf, мы можем работать со своим файлом как с обычной областью памяти, не заботясь о вводе, выводе, позиционировании и т.п. Все эти проблемы берет на себя файловая система. Последняя функция, имеющая отношение к объекту файлового отображения, называется UnMapViewOfFile. Функция UnMapViewOfFile прекращает отображение в адресное пространство процесса того файла, который перед этим был отображен При помощи функции MapViewOfFile. Ну а Функцией CloseHandle закрываем дескриптор объекта файлового отображения. Сделаем это, например, при разрушении формы:
procedure TForm1.FormDestroy(Sender: TObject);
begin
//чистим за собой
UnMapViewOfFile(pSharedBuf);
CloseHandle(hMappedFile);
end;
Вот в принципе и всё! Главное не забывай освобождать после себя память. И очень внимательно проверяй все параметры функций. Допустишь ошибку - всё, прога не работает!