Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In het volgende voorbeeld ziet u hoe de dll-invoerpuntfunctie een object voor bestandstoewijzing kan gebruiken om geheugen in te stellen dat kan worden gedeeld door processen die het DLL-bestand laden. Het gedeelde DLL-geheugen blijft behouden zolang het DLL-bestand is geladen. Toepassingen kunnen de functies SetSharedMem en GetSharedMem gebruiken voor toegang tot het gedeelde geheugen.
DLL waarmee het gedeelde geheugen wordt geïmplementeerd
In het voorbeeld wordt bestandstoewijzing gebruikt om een blok met benoemd gedeeld geheugen toe te wijzen aan de virtuele adresruimte van elk proces waarmee het DLL-bestand wordt geladen. Hiervoor moet de invoerpuntfunctie het volgende doen:
- Roep de functie CreateFileMapping aan om een ingang op te halen naar een object voor bestandstoewijzing. Het eerste proces waarmee het DLL-bestand wordt geladen, maakt het object voor bestandstoewijzing. Volgende processen openen een ingang voor het bestaande object. Zie Een File-Mapping-object makenvoor meer informatie.
- Roep de functie MapViewOfFile aan om een weergave in de virtuele adresruimte te mappen. Hierdoor kan het proces toegang krijgen tot het gedeelde geheugen. Zie Een bestandsweergave makenvoor meer informatie.
Hoewel u standaardbeveiligingskenmerken kunt opgeven door een NULL-waarde door te geven voor de lpAttributes parameter van CreateFileMapping, kunt u ervoor kiezen om een SECURITY_ATTRIBUTES structuur te gebruiken om extra beveiliging te bieden.
// The DLL code
#include <windows.h>
#include <memory.h>
#define SHMEMSIZE 4096
static LPVOID lpvMem = NULL; // pointer to shared memory
static HANDLE hMapObject = NULL; // handle to file mapping
// The DLL entry-point function sets up shared memory using a
// named file-mapping object.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{
BOOL fInit, fIgnore;
switch (fdwReason)
{
// DLL load due to process initialization or LoadLibrary
case DLL_PROCESS_ATTACH:
// Create a named file mapping object
hMapObject = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
SHMEMSIZE, // size: low 32-bits
TEXT("dllmemfilemap")); // name of map object
if (hMapObject == NULL)
return FALSE;
// The first process to attach initializes memory
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
// Get a pointer to the file-mapped shared memory
lpvMem = MapViewOfFile(
hMapObject, // object to map view of
FILE_MAP_WRITE, // read/write access
0, // high offset: map from
0, // low offset: beginning
0); // default: map entire file
if (lpvMem == NULL)
return FALSE;
// Initialize memory if this is the first process
if (fInit)
memset(lpvMem, '\0', SHMEMSIZE);
break;
// The attached process creates a new thread
case DLL_THREAD_ATTACH:
break;
// The thread of the attached process terminates
case DLL_THREAD_DETACH:
break;
// DLL unload due to process termination or FreeLibrary
case DLL_PROCESS_DETACH:
// Unmap shared memory from the process's address space
fIgnore = UnmapViewOfFile(lpvMem);
// Close the process's handle to the file-mapping object
fIgnore = CloseHandle(hMapObject);
break;
default:
break;
}
return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}
// The export mechanism used here is the __declspec(export)
// method supported by Microsoft Visual Studio, but any
// other export method supported by your development
// environment may be substituted.
#ifdef __cplusplus // If used by C++ code,
extern "C" { // we need to export the C interface
#endif
// SetSharedMem sets the contents of the shared memory
__declspec(dllexport) VOID __cdecl SetSharedMem(LPWSTR lpszBuf)
{
LPWSTR lpszTmp;
DWORD dwCount=1;
// Get the address of the shared memory block
lpszTmp = (LPWSTR) lpvMem;
// Copy the null-terminated string into shared memory
while (*lpszBuf && dwCount<SHMEMSIZE)
{
*lpszTmp++ = *lpszBuf++;
dwCount++;
}
*lpszTmp = '\0';
}
// GetSharedMem gets the contents of the shared memory
__declspec(dllexport) VOID __cdecl GetSharedMem(LPWSTR lpszBuf, DWORD cchSize)
{
LPWSTR lpszTmp;
// Get the address of the shared memory block
lpszTmp = (LPWSTR) lpvMem;
// Copy from shared memory into the caller's buffer
while (*lpszTmp && --cchSize)
*lpszBuf++ = *lpszTmp++;
*lpszBuf = '\0';
}
#ifdef __cplusplus
}
#endif
Gedeeld geheugen kan in elk proces worden toegewezen aan een ander adres. Daarom heeft elk proces een eigen exemplaar van lpvMem, dat wordt gedeclareerd als een globale variabele, zodat deze beschikbaar is voor alle DLL-functies. In het voorbeeld wordt ervan uitgegaan dat de globale DLL-gegevens niet worden gedeeld, dus elk proces dat het DLL-bestand laadt, heeft een eigen exemplaar van lpvMem.
Houd er rekening mee dat het gedeelde geheugen wordt vrijgegeven wanneer de laatste handle voor de bestandskoppelingsobject wordt gesloten. Als u persistente gedeeld geheugen wilt maken, moet u ervoor zorgen dat een bepaald proces altijd een open handle heeft naar het bestandstoewijzingsobject.
Processen die gebruikmaken van het gedeelde geheugen
In de volgende processen wordt gebruikgemaakt van het gedeelde geheugen dat wordt geleverd door de hierboven gedefinieerde DLL. Met het eerste proces wordt SetSharedMem aangeroepen om een tekenreeks te schrijven terwijl het tweede proces GetSharedMem aanroept om deze tekenreeks op te halen.
Dit proces maakt gebruik van de functie SetSharedMem die door het DLL-bestand is geïmplementeerd om de tekenreeks 'Dit is een testreeks' naar het gedeelde geheugen te schrijven. Er wordt ook een onderliggend proces gestart waarmee de tekenreeks uit het gedeelde geheugen wordt gelezen.
// Parent process
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
extern "C" VOID __cdecl SetSharedMem(LPWSTR lpszBuf);
HANDLE CreateChildProcess(LPTSTR szCmdline)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
// Set up members of the STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
// Create the child process.
bFuncRetn = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (bFuncRetn == 0)
{
printf("CreateProcess failed (%)\n", GetLastError());
return INVALID_HANDLE_VALUE;
}
else
{
CloseHandle(piProcInfo.hThread);
return piProcInfo.hProcess;
}
}
int _tmain(int argc, TCHAR *argv[])
{
HANDLE hProcess;
if (argc == 1)
{
printf("Please specify an input file");
ExitProcess(0);
}
// Call the DLL function
printf("\nProcess is writing to shared memory...\n\n");
SetSharedMem(L"This is a test string");
// Start the child process that will read the memory
hProcess = CreateChildProcess(argv[1]);
// Ensure this process is around until the child process terminates
if (INVALID_HANDLE_VALUE != hProcess)
{
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
}
return 0;
}
Dit proces maakt gebruik van de functie GetSharedMem die door het DLL-bestand is geïmplementeerd om een tekenreeks uit het gedeelde geheugen te lezen. Het wordt gestart door het bovenliggende proces hierboven.
// Child process
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
extern "C" VOID __cdecl GetSharedMem(LPWSTR lpszBuf, DWORD cchSize);
int _tmain( void )
{
WCHAR cBuf[MAX_PATH];
GetSharedMem(cBuf, MAX_PATH);
printf("Child process read from shared memory: %S\n", cBuf);
return 0;
}
Verwante onderwerpen