- Спойлер
- Пример ниже демонстрирует, как функция точки входа в DLL может использовать объект "проекция файла в память", чтобы установить память, которая может быть совместно использоваться процессами, загружающими DLL. Разделяемая память DLL сохраняется только до тех пор, пока DLL загружена. Приложения могут использовать функции SetSharedMem и GetSharedMem, чтобы получить доступ к совместно используемой памяти.
Пример использует проекцию файла в память, чтобы отобразить блок именованной совместно используемой памяти в виртуальное адресное пространство каждого процесса, который загружает DLL. Чтобы сделать это, функция точки входа должна:
Вызвать функцию CreateFileMapping, чтобы получить дескриптор объекта "проекция файла в память". Первый процесс, который загружает DLL, создает объект "проекция файла в память". Последующие процессы открывают дескриптор существующего объекта. Дополнительную информацию, см. в статье Создание объекта "проецируемый файл".
Вызвать функцию MapViewOfFile, чтобы проецировать представление в виртуальное адресное пространство. Это дает возможность процессу получить доступ к совместно используемой памяти. Дополнительную информацию, см. в статье Создание представления данных файла.Код: Выделить всё
// Функция точки входа в DLL подготавливает разделяемую
// память используя именованный объект "проекция файла
// в память".
#include <windows.h>
#include <memory.h>
#define SHMEMSIZE 4096
static LPVOID lpvMem = NULL; // указатель на разделяемую
// память
static HANDLE hMapObject = NULL; // дескриптор отображенного
// файла
BOOL DllMain(HINSTANCE hinstDLL, // дескриптор модуля DLL
DWORD fdwReason, // причина вызова
LPVOID lpvReserved) // зарезервирован
{
BOOL fInit, fIgnore;
switch (fdwReason)
{
// DLL загружается соответствующим процессом
// инициализации или вызовом LoadLibrary.
case DLL_PROCESS_ATTACH:
// Создаем именованный объект "проекция файла".
hMapObject = CreateFileMapping(
INVALID_HANDLE_VALUE, // используем файл подкачки
NULL, // атрибуты защиты по умолчанию
PAGE_READWRITE, // доступ к чтению/записи
0, // размер: старшие 32 бита
SHMEMSIZE, // размер: младшие 32 бита
"dllmemfilemap"); // имя объекта отображения
if (hMapObject == NULL)
return FALSE;
// Первый процесс, который присоединяем к
// инициализируемой памяти.
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
// Получим указатель на отображение файла
// в разделяемой памяти.
lpvMem = MapViewOfFile(
hMapObject, // объект представления проецирования
FILE_MAP_WRITE, // доступ к чтению записи
0, // старшее смещение: от отображения
0, // младшее смещение: начало
0); // по умолчанию: проекция всего файла if (lpvMem == NULL)
return FALSE;
// Инициализация памяти, если она для первого процесса.
if (fInit)
memset(lpvMem, '\0', SHMEMSIZE);
break;
// Связанный процесс создает новый поток.
case DLL_THREAD_ATTACH:
break;
// Поток связанного процесса заканчивает работу.
case DLL_THREAD_DETACH:
break;
// DLL выгружается из процесса вследствие
// завершение работы процесса или вызова FreeLibrary.
case DLL_PROCESS_DETACH:
// Отменяет отображение совместно используемой памяти
// от адресного пространства процесса.
fIgnore = UnmapViewOfFile(lpvMem);
// Закрываем дескриптор процесса объекта
// "проекция файла в память".
fIgnore = CloseHandle(hMapObject);
break;
default:
break;
}
return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}
// SetSharedMem устанавливает содержание совместно
// используемой памяти.
VOID SetSharedMem(LPSTR lpszBuf)
{
LPSTR lpszTmp;
// Получим адрес блока совместно используемой памяти.
lpszTmp = (LPSTR) lpvMem;
// Копируем символьную строку с нулем в конце в
// совместно используемую память.
while (*lpszBuf)
*lpszTmp++ = *lpszBuf++;
*lpszTmp = '\0';
}
// GetSharedMem получает содержание совместно
// используемой памяти.
VOID GetSharedMem(LPSTR lpszBuf, DWORD cchSize)
{
LPSTR lpszTmp;
// Получаем адрес блока совместно используемой памяти.
lpszTmp = (LPSTR) lpvMem;
// Копируем совместно используемую память в буфер
// вызывающей программы.
while (*lpszTmp && --cchSize)
*lpszBuf++ = *lpszTmp++;
*lpszBuf = '\0';
}