关于在动态链接库中共享存储的简单示例,译自MSDN

类别:编程语言 点击:0 评论:0 推荐:

  本节将示范如何利用文件映像使得入口点函数创建可被载入该DLL的进程共享的存储。该共享的DLL存储仅存活于DLL载入期间。

  示例通过文件映像把一个命名的共享存储块映射到载入DLL的每个进程的虚地址空间中。要达到该目的,入口点函数必须:

 调用 CreateFileMapping 函数获取一个文件映像对象的句柄。第一个载入DLL的进程创建文件映像对象,后续的进程仅打开存在对象的句柄。更多信息,参照“文件映像对象”。 通过调用 MapViewOfFile 函数可以把一个view映射到虚地址空间,使得进程能访问共享存储。更多信息,参照创建文件视图(File View)。

(译者注:通过查看MapViewOfFile的详细说明,MapViewOfFile把一个文件的View映射到调用进程的地址空间内;并根据以下代码,我认为View在这里翻译成视图应该是可以的,File View应该表示的是文件的一种查看方式)

// File: DLLSHMEM.C. // The DLL entry-point function sets up shared memory using // a named file-mapping object. #include <windows.h> #include <memory.h> #define SHMEMSIZE 4096 static LPVOID lpvMem = NULL; // pointer to shared memory BOOL DllMain(HINSTANCE hinstDLL, // DLL module handle DWORD fdwReason, // reason called LPVOID lpvReserved) // reserved { HANDLE hMapObject = NULL; // handle to file mapping BOOL fInit, fIgnore; switch (fdwReason) { // The DLL is loading due to process // initialization or a call to 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 "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, // 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; // The DLL is unloading from a process due to // process termination or a call to 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); } // SetSharedMem sets the contents of shared memory. VOID SetSharedMem(LPTSTR lpszBuf) { LPTSTR lpszTmp; // Get the address of the shared memory block. lpszTmp = (LPTSTR) lpvMem; // Copy the null-terminated string into shared memory. while (*lpszBuf) *lpszTmp++ = *lpszBuf++; *lpszTmp = '\0'; } // GetSharedMem gets the contents of shared memory. VOID GetSharedMem(LPTSTR lpszBuf, DWORD cchSize) { LPTSTR lpszTmp; // Get the address of the shared memory block. lpszTmp = (LPTSTR) lpvMem; // Copy from shared memory into the caller's buffer. while (*lpszTmp && --cchSize) *lpszBuf++ = *lpszTmp++; *lpszBuf = '\0'; }

注意 共享存储能被映射到每个进程的不同地址中,所以,每个进程拥有自己的lpvMem参数实例,该参数作为全局变量声明,对DLL中所有函数都可用。该例假定DLL的全局数据不共享,所以,载入每个进程该DLL的进程都有自己的lpvMem实例。

  该例中,文件映像对象最后一个句柄关闭时,共享内存将释放,要创建永久的共享内存,DLL可以在首次载入时,通过一个分派处理创建。如果分派处理使用了DLL,而且没有终止,就会得到一个到拒绝释放共享内存的文件映射对象的句柄。

本文地址:http://com.8s8s.com/it/it22869.htm