在需要做进程隔离的应用中,共享内存成为一种建立全局共享数据的有效方式。
CreateFileMapping:为指定文件创建或打开命名或未命名的文件映射对象。
OpenFileMapping:打开命名文件映射对象。
MapViewOfFile:映射到进程空间。
UnmapViewOfFile:解除映射。
#include
#include "tchar.h"
#include "winnt.h"
#include
#define BUF_SIZE 4096
#define BUF_ID TEXT("ShareMemoryPDU")
//全局共享内存
class WindowsGlobalShareMemery
{
public:
WindowsGlobalShareMemery(){
m_hClientMapFile = NULL;
m_lpClientBase = NULL;
}
~WindowsGlobalShareMemery(){
}
//调用端将数据写入内存
bool ClientCreateBuff(std::string strData){
// 创建共享文件句柄
m_hClientMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // 物理文件句柄 NVALID_HANDLE_VALUE 则创建一个进程间共享的对象
NULL, // 默认安全级别
PAGE_READWRITE, // 可读可写
0, // 高位文件大小
BUF_SIZE, // 低位文件大小
BUF_ID // 映射文件名,即共享内存的名称
);
if (0 == m_hClientMapFile)
{
return false;
}
// 映射缓存区视图 , 得到指向共享内存的指针
// 将hFileMapping共享内存衍射到本进程的地址空间中
m_lpClientBase = MapViewOfFile(
m_hClientMapFile, // 共享内存的句柄
FILE_MAP_ALL_ACCESS, // 可读写许可
0,
0,
BUF_SIZE);
if (0 == m_lpClientBase)
{
return false;
}
//数据复制向共享内存
strcpy((char*)m_lpClientBase, strData.data());
//成功返回
return true;
}
//调用端读取返回数据
bool ClientReadBuff(std::string& strData){
//字符串数据从共享内存复制到字符串
strData = (char*)m_lpClientBase;
return true;
}
//返回后清除共享内存
void ClientClearBuff(){
// 解除文件映射
if (m_lpClientBase)
{
UnmapViewOfFile(m_lpClientBase);
}
// 关闭内存映射文件对象句柄
if (m_hClientMapFile)
{
CloseHandle(m_hClientMapFile);
}
}
//服务器端打开读取数据
static bool ServerReadBuf(std::string& strData){
// 打开共享的文件对象
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, BUF_ID);
if (0 == hMapFile)
{
// 打开共享内存句柄失败
return false;
}
LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (0 == lpBase)
{
return false;
}
//字符串数据复制
char szBuffer[BUF_SIZE]{ 0 };
strcpy_s(szBuffer, (char*)lpBase);
strData = szBuffer;
// 解除文件映射
UnmapViewOfFile(lpBase);
// 关闭内存映射文件对象句柄
CloseHandle(hMapFile);
return true;
}
//服务器端打开读取数据
static bool ServerWriteBuf(std::string strData){
// 打开共享的文件对象
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, BUF_ID);
if (0 == hMapFile)
{
// 打开共享内存句柄失败
return false;
}
LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (0 == lpBase)
{
return false;
}
//数据复制向共享内存
memset(lpBase, 0, BUF_SIZE);
strcpy((char*)lpBase, strData.data());
// 解除文件映射
UnmapViewOfFile(lpBase);
// 关闭内存映射文件对象句柄
CloseHandle(hMapFile);
return true;
}
//启动应用程序
static bool StartApplicationByAPI(const char* exeFilename){
STARTUPINFOA stStartUpInfo;
::memset(&stStartUpInfo, 0, sizeof(stStartUpInfo));
stStartUpInfo.cb = sizeof(stStartUpInfo);
stStartUpInfo.wShowWindow = SW_HIDE;
//stStartUpInfo.wShowWindow = SW_SHOW;
PROCESS_INFORMATION stProcessInfo;
::memset(&stProcessInfo, 0, sizeof(stProcessInfo));
char szPath[256] = { 0 };
strcat_s(szPath, exeFilename);
char szCmd[256] = { 0 };
try
{
bool bRet = ::CreateProcessA(
szPath,
szCmd,
NULL,
NULL,
false,
CREATE_NO_WINDOW,
//CREATE_NEW_CONSOLE, //显示控制台调试
NULL,
NULL,
&stStartUpInfo,
&stProcessInfo);
if (bRet)
{
WaitForSingleObject(stProcessInfo.hProcess, -1);
::CloseHandle(stProcessInfo.hProcess);
::CloseHandle(stProcessInfo.hThread);
stProcessInfo.hProcess = NULL;
stProcessInfo.hThread = NULL;
stProcessInfo.dwProcessId = 0;
stProcessInfo.dwThreadId = 0;
}
else
{
//如果创建进程失败,查看错误码
DWORD dwErrCode = GetLastError();
printf_s("ErrCode : %d\n", dwErrCode);
}
}
catch (...)
{
}
return true;
}
private:
HANDLE m_hClientMapFile;
LPVOID m_lpClientBase;
};
主程序使用,调用隔离进程程序。
int _tmain(int argc, _TCHAR* argv[])
{
WindowsGlobalShareMemery tWindowsGlobalShareMemery;
tWindowsGlobalShareMemery.ClientCreateBuff("123456789");
WindowsGlobalShareMemery::StartApplicationByAPI("E:/work/个人/微博/Python/WebTool/C++/ShareMemeryClient/Debug/server.exe");
std::string retData;
tWindowsGlobalShareMemery.ClientReadBuff(retData);
tWindowsGlobalShareMemery.ClientClearBuff();
return 0;
}
功能端使用,执行完毕返回。
int _tmain(int argc, _TCHAR* argv[])
{
std::string data;
WindowsGlobalShareMemery::ServerReadBuf(data);
printf("%s\n", data.c_str());
WindowsGlobalShareMemery::ServerWriteBuf("987654321");
system("pause");
return 0;
}
通过使用共享内存将数据传递到目标进程,目标进程使用完毕之后,返回结果,主程序读取结果,释放共享数据。更复杂的端对端通信,可能采取更复杂的方式来通信。