Windows process communication -- shared memory

Keywords: Windows

I. knowledge points

The following functions are mainly used, and the specific meaning of parameters can be Baidu

1.CreateFileMapping,OpenFileMapping,MapViewOfFile

2.CreateEvent,SetEvent,ResetEvent,WaitForSingleObject

 

Two, function

The logic is simple:

1. First open the shared memory according to the name. If it fails to open, create it. Then call MapViewOfFile to get the address of shared memory.

2. start a thread, use event to detect whether there is data in shared memory, if there is data, read it, then call data processing function to process.

Code:

ShareMemory.h

#ifndef SHAREMEMORY_H
#define SHAREMEMORY_H

#include <string>
#include <thread>
#include <memory>
#include "Windows.h"

class ShareMemory
{
public:
	ShareMemory(std::wstring strKey, unsigned int nSize = 1024);
	~ShareMemory();

	void registeReceiver(std::function<void(char *)> pfunReceiver);
	void writeData(char *data, int nLength);

private:
	void readData();

private:
	std::shared_ptr<std::thread> m_ptrReadThread;
	bool m_bThreadRunning = true;

	HANDLE m_hMapFile = nullptr;
	LPVOID m_buffer = nullptr;

	std::function<void(char *)> m_pfunReceiver = nullptr;
	
	std::wstring m_strUniqueId;
	HANDLE m_writeEvent = nullptr;
};

#endif

ShareMemory.cpp

#include "stdafx.h"
#include "ShareMemory.h"
#include <iostream>


ShareMemory::ShareMemory(std::wstring strKey, unsigned int nSize)
{
	m_strUniqueId = std::move(strKey);
	m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, m_strUniqueId.c_str());
	if (!m_hMapFile)
	{
		m_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, nSize, m_strUniqueId.c_str());
	}

	if (m_hMapFile)
	{
		m_buffer = MapViewOfFile(m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, nSize);

		if (!m_buffer)
		{
			CloseHandle(m_hMapFile);
		}
		else
		{
			
			
			std::wstring strWriteKey = m_strUniqueId;
			strWriteKey.append(L"_write");
			m_writeEvent = CreateEvent(NULL, TRUE, FALSE, strWriteKey.c_str());

			memset(m_buffer, 0, nSize);
			m_ptrReadThread = std::make_shared<std::thread>(std::bind(&ShareMemory::readData, this));
		}
	}
}


ShareMemory::~ShareMemory()
{
	if (m_buffer)
	{
		UnmapViewOfFile(m_buffer);
		m_buffer = nullptr;
	}

	if (m_hMapFile)
	{
		CloseHandle(m_hMapFile);
		m_hMapFile = nullptr;
	}

	if (m_writeEvent)
	{
		CloseHandle(m_writeEvent);
		m_writeEvent = nullptr;
	}
	
}

void ShareMemory::registeReceiver(std::function<void(char *)> pfunReceiver)
{
	m_pfunReceiver = pfunReceiver;
}

void ShareMemory::writeData(char *data, int nLength)
{
	if (m_writeEvent)
	{
		memcpy(m_buffer, data, nLength);
		SetEvent(m_writeEvent);
	}	
}

void ShareMemory::readData()
{
	if (!m_writeEvent)
	{
		return;
	}

	while (m_bThreadRunning)
	{
		DWORD  dwWaitResult = WaitForSingleObject(m_writeEvent, INFINITE);
		switch (dwWaitResult)
		{
			// Event object was signaled
		case WAIT_OBJECT_0:
		{
			if (m_pfunReceiver)
			{
				char *data = (char*)m_buffer;
				int nLen = strlen(data);
				m_pfunReceiver(data);
				memset(m_buffer, 0, nLen);
				ResetEvent(m_writeEvent);
			}
			break;
		}

		default:
			std::cout<<"Wait error :" << GetLastError()<<std::endl;
			break;
		}
	}
	
	
}

Write data process

int main(int *argc, char *argv[])
{
	ShareMemory sm(L"mysharememory");

	while (true)
    {
		char in[100];
		std::cin >> in;
		sm.writeData(in, strlen(in));
	}


	system("pause");
    return 0;
}

Read data process

int main(int *argc, char *argv[])
{
	ShareMemory sm(L"mysharememory");

	std::string i = std::string(argv[1]);

	
	sm.registeReceiver([](char *data) {
		std::cout << data << std::endl;
	});
	

	system("pause");
    return 0;
}

Three, problems

The logic of this code is relatively simple. It has realized the data reading and writing of shared memory, but there are still many scenarios that have not been processed. Next, we will modify it

 

Posted by ScubaDvr2 on Thu, 28 Nov 2019 08:23:43 -0800