C++-Win32-共享内存-传递数据-进程隔离

文章目录

    • 1.共享内存
    • 2.调用端使用
    • 3.服务端使用
    • 4.总结

1.共享内存

在需要做进程隔离的应用中,共享内存成为一种建立全局共享数据的有效方式。

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;
};

2.调用端使用

主程序使用,调用隔离进程程序。

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;
}

3.服务端使用

功能端使用,执行完毕返回。

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;
}

4.总结

通过使用共享内存将数据传递到目标进程,目标进程使用完毕之后,返回结果,主程序读取结果,释放共享数据。更复杂的端对端通信,可能采取更复杂的方式来通信。

你可能感兴趣的:(C++,Windows,c++,Win32,共享内存,传递数据,进程隔离)