引用自:http://blog.csdn.net/starlee/archive/2007/06/01/1633762.aspx
我們知道,在Windows中的每個進程都有自己獨立的內存空間。該獨立的內存空間包含了所有的可執行模塊或DLL模塊的代碼和數據以及動態內存分配的空間。每個進程的內存空間只能被該進程訪問,其他進程是不能訪問的。
如果我們要想在進程間共享內存(也就是創建一塊不同進程都能訪問的內存),那就必須使用內核對象。因爲內核對象由Windows系統內核所擁有,而不是由進程所擁有。
下面就用文件映射(File Mapping)和互斥量(Mutex)兩中內核對象來實現簡單的進程間內存共享。文件映射(File Mapping)用來開闢共享的內存空間,而互斥量(Mutex)則是用來使讀寫互斥。 Windows,實際上只有映像文件共享內存一種。
在該例子裏,實現了下面5個函數用來進行進程間的內存共享。可以把這5個函數放到一個DLL裏面當成輸出函數來用。在進程里加載該DLL並調用相應的函數就可實現進程間內存共享。
首先,定義返回值代碼:
typedef enum
{
LX_OK = 0, // 正常返回
LX_SHAREDMEMORY_EXISTS = 1, // 共享內存已經存在
LX_INVALID_SHAREDMEMORY = 2, // 共享內存錯誤返回
LX_INVALID_SIZE = 3 // 共享內存大小錯誤
}LX_RETURN_VALUE; 然後,是函數聲明:
// 創建共享內存
LX_RETURN_VALUE CreateSharedMemory(UINT nSize);
// 釋放共享內存
LX_RETURN_VALUE ReleaseSharedMemory();
// 得到共享內存大小
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize);
// 向共享內存寫入數據
LX_RETURN_VALUE WriteToSharedMemory(void *pData, UINT nSize);
// 從共享內存讀取數據
LX_RETURN_VALUE ReadFromSharedMemory(void *pData, UINT nSize); 下面是函數的實現:
// 互斥量
CMutex g_mMutex(FALSE, "StarLeeMutex");
LX_RETURN_VALUE CreateSharedMemory(UINT nSize)
{
// 創建共享內存塊
HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nSize, "StarLeeSharedMemory");
// 創建錯誤
if ((hFileMapping == NULL) || (hFileMapping == INVALID_HANDLE_VALUE))
return LX_INVALID_SHAREDMEMORY;
// 共享內存已經存在
if (GetLastError() == ERROR_ALREADY_EXISTS)
return LX_SHAREDMEMORY_EXISTS;
// 創建另外一塊內存存放共享內存的大小
HANDLE hSize = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, sizeof(UINT), "StarLeeSharedMemorySize");
if ((hSize == NULL) || (hSize == INVALID_HANDLE_VALUE) || (GetLastError() == ERROR_ALREADY_EXISTS))
return LX_INVALID_SHAREDMEMORY;
// 得到存放共享內存大小的指針
UINT *pSize = (UINT *)MapViewOfFile(hSize, FILE_MAP_WRITE, 0, 0, sizeof(UINT));
if (pSize == NULL)
return LX_INVALID_SHAREDMEMORY;
// 寫入共享內存的大小
memcpy(pSize, &nSize, sizeof(UINT));
UnmapViewOfFile(pSize);
return LX_OK;
}
LX_RETURN_VALUE ReleaseSharedMemory()
{
g_mMutex.Lock();
// 打開共享內存
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "StarLeeSharedMemory");
// 關閉共享內存
if (hFileMapping != NULL)
CloseHandle(hFileMapping);
// 打開存放共享內存大小的文件映射
HANDLE hSize = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "StarLeeSharedMemorySize");
// 關閉存放共享內存大小的文件映射
if (hSize != NULL)
CloseHandle(hSize);
g_mMutex.Unlock();
return LX_OK;
}
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize)
{
g_mMutex.Lock();
HANDLE hSize = OpenFileMapping(FILE_MAP_READ, FALSE, "StarLeeSharedMemorySize");
if (hSize == NULL)
{
g_mMutex.Unlock();
return LX_INVALID_SHAREDMEMORY;
}
UINT *pSize = (UINT *)MapViewOfFile(hSize, FILE_MAP_READ, 0, 0, sizeof(UINT));
if (pSize == NULL)
{
g_mMutex.Unlock();
return LX_INVALID_SHAREDMEMORY;
}
// 得到共享內存的大小
memcpy(&nSize, pSize, sizeof(UINT));
g_mMutex.Unlock();
return LX_OK;
}
LX_RETURN_VALUE WriteToSharedMemory(void *pDate, UINT nSize)
{
g_mMutex.Lock();
UINT nSharedMemorySize = 0;
// 得到共享內存的大小
if (GetSharedMemorySize(nSharedMemorySize) != LX_OK)
return LX_INVALID_SHAREDMEMORY;
// 檢查共享內存的大小
if (nSize > nSharedMemorySize)
return LX_INVALID_SIZE;
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_WRITE, FALSE, "StarLeeSharedMemory");
if (hFileMapping == NULL)
{
g_mMutex.Unlock();
return LX_INVALID_SHAREDMEMORY;
}
void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, nSize);
if (pMapView == NULL)
{
g_mMutex.Unlock();
return LX_INVALID_SHAREDMEMORY;
}
// 將數據寫入共享內存
memcpy(pMapView, pDate, nSize);
UnmapViewOfFile(pMapView);
g_mMutex.Unlock();
return LX_OK;
}
LX_RETURN_VALUE ReadFromSharedMemory(void *pData, UINT nSize)
{
g_mMutex.Lock();
UINT nSharedMemorySize = 0;
if (GetSharedMemorySize(nSharedMemorySize) != LX_OK)
return LX_INVALID_SHAREDMEMORY;
if (nSize > nSharedMemorySize)
return LX_INVALID_SIZE;
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE, "StarLeeSharedMemory");
if (hFileMapping == NULL)
{
g_mMutex.Unlock();
return LX_INVALID_SHAREDMEMORY;
}
void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, nSize);
if (pMapView == NULL)
{
g_mMutex.Unlock();
return LX_INVALID_SHAREDMEMORY;
}
// 從共享內存讀取數據
memcpy(pData, pMapView, nSize);
UnmapViewOfFile(pMapView);
g_mMutex.Unlock();
return LX_OK;
}
用到的主要接口有:
The CreateFileMapping function creates or opens a named or unnamed file mapping object for the specified file.
HANDLE CreateFileMapping( HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName);The MapViewOfFile function maps a view of a file into the address space of the calling process.
To specify a suggested base address, use the MapViewOfFileEx function.
LPVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap );
The OpenFileMapping function opens a named file mapping object.
HANDLE OpenFileMapping( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/ruixj/archive/2007/06/05/1639555.aspx