关于多线程/多进程通信,一直是程序员们很难过去的一道坎;熟知MFC技术的程序员也许并不担心这些;因为MFC的技术足够强大;如果你是用C和API开发的话。
会遇到很多抓狂的事情。最近闲来无事,复习了一下这方面的东西。记录下来与大家共勉。由于本人能力有限,错误之处还请大家批评指正。
描述问题:A进程想做一件事情;做这件事情的前提是,B进程必须提供好充要条件。当B进程完成这个充要条件时,通知A进程,然后A进程开始做;这是一个典型的
多进程/线程间的通信实例。接下来用代码分析这些事情的来龙去脉;
首先介绍读共享内存部分以下是类实现:
定义文件
#pragma once
#define MEMORY_SIZE 1024
#define GLOBAL_MEMORY_NAME TEXT("Global\\ShareMemory")
#define GLOBAL_EVENT_NAME TEXT("Global\\ShareMemoryEvent")
头文件
#pragma once
#include <Windows.h>
#include <tchar.h>
class ShareWriteMemory
{
public:
ShareWriteMemory();
~ShareWriteMemory();
public:
bool OnInit();
bool OnWriteMemory(IN char* pszData);
private:
HANDLE m_hEvent;
HANDLE m_hShareHandle;
};
实现文件
#include "ShareWriteMemory.h"
#include "ShareDefine.h"
ShareWriteMemory::ShareWriteMemory()
{
m_hEvent = NULL;
m_hShareHandle = NULL;
}
ShareWriteMemory::~ShareWriteMemory()
{
if (NULL != m_hShareHandle)
{
CloseHandle(m_hShareHandle);
m_hShareHandle = NULL;
CloseHandle(m_hEvent);
m_hEvent = NULL;
}
}
bool ShareWriteMemory::OnInit()
{
m_hShareHandle = OpenFileMapping(
FILE_MAP_WRITE,
FALSE,
GLOBAL_MEMORY_NAME);
if (NULL == m_hShareHandle)
{
return false;
}
m_hEvent = OpenEvent(EVENT_MODIFY_STATE,TRUE,GLOBAL_EVENT_NAME);
if (NULL == m_hEvent)
{
return false;
}
return true;
}
bool ShareWriteMemory::OnWriteMemory(IN char* pszData)
{
if (NULL == pszData)
{
return false;
}
char* pBuffer = NULL;
if (NULL == m_hShareHandle)
{
return false;
}
pBuffer = (char*)MapViewOfFile(
m_hShareHandle,
FILE_MAP_WRITE,
0,
0,
MEMORY_SIZE);
if (NULL == pBuffer)
{
return false;
}
__try
{
ZeroMemory(pBuffer, strlen(pBuffer));
CopyMemory((void*)pBuffer, pszData, strlen(pszData));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
UnmapViewOfFile(pBuffer);
return false;
}
UnmapViewOfFile(pBuffer);
SetEvent(m_hEvent);
return true;
}
测试用例实现
#include <windows.h>
#include "ShareWriteMemory.h"
#include <string>
#include <fstream>
using namespace std;
/*
* date: 02/26/2012
* note: I want to write some clean code. but, I can't today!
* maybe ... sure I can.
*/
int main(int argc, char** argv)
{
string text;
char buffer[1024] = {0};
ShareWriteMemory WriteMemory;
if (!WriteMemory.OnInit())
{
printf("Write Memory is error!\n");
return -1;
}
ifstream file("data", ios::in);
while(getline(file,text,'\n'))
{
CopyMemory(buffer, text.c_str(), text.length());
if (!WriteMemory.OnWriteMemory(buffer))
{
printf("write memory block is error.\n");
break;
}
Sleep(1000);
}
return 0;
}
备注:这个测试用例是以按行读取一个文件内容并写入共享内存为目的设计的;
其实我们还可以这样:因为写入的是一块内存,我们可以修改OnWriteMemory的参数为void*类型,这样我们可以将一个结构体写入内存;
如果你想知道具体细节我觉得我们有必要更深入的探讨。代码写到这里过多的就不解释了。希望您可以认真阅读。体会我的想法。
读内存头文件设计
#pragma once
#include <Windows.h>
#include <tchar.h>
class ShareReadMemory
{
public:
ShareReadMemory();
~ShareReadMemory();
public:
bool OnInit();
bool OnReadMemory(OUT char* pszData);
private:
HANDLE m_hEvent;
HANDLE m_hShareHandle;
};
#include "ShareReadMemory.h"
#include "ShareDefine.h"
ShareReadMemory::ShareReadMemory()
{
m_hEvent = NULL;
m_hShareHandle = NULL;
}
ShareReadMemory::~ShareReadMemory()
{
if (NULL != m_hShareHandle)
{
CloseHandle(m_hShareHandle);
m_hShareHandle = NULL;
CloseHandle(m_hEvent);
m_hEvent = NULL;
}
}
bool ShareReadMemory::OnInit()
{
m_hShareHandle = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
MEMORY_SIZE,
GLOBAL_MEMORY_NAME);
if (NULL == m_hShareHandle)
{
return false;
}
m_hEvent = CreateEvent(NULL, FALSE, FALSE, GLOBAL_EVENT_NAME);
if (NULL == m_hEvent)
{
return false;
}
return true;
}
bool ShareReadMemory::OnReadMemory(OUT char* pszData)
{
WaitForSingleObject(m_hEvent, INFINITE);
if (NULL == pszData)
{
return false;
}
if (NULL == m_hShareHandle)
{
return false;
}
char* pBuffer = NULL;
pBuffer = (LPSTR)MapViewOfFile(
m_hShareHandle,
FILE_MAP_READ,
0,
0,
MEMORY_SIZE);
if (NULL == pBuffer)
{
return false;
}
__try
{
CopyMemory((void*)pszData, pBuffer, strlen(pBuffer));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
UnmapViewOfFile(pBuffer);
return false;
}
UnmapViewOfFile(pBuffer);
PulseEvent(m_hEvent);
return true;
}
测试用例实现代码
#include <windows.h>
#include <stdio.h>
#include "ShareReadMemory.h"
int main(int argc, char** argv)
{
ShareReadMemory ReadMemory;
if (!ReadMemory.OnInit())
{
printf("Read Memory is error!\n");
return -1;
}
char buffer[1024] = {0};
while (ReadMemory.OnReadMemory(buffer))
{
if (0 == strncmp("DONE", buffer, 4))
{
break;
}
if (NULL != buffer)
{
printf("TA这样地说->%s\n\n", buffer);
}
else
{
continue;
}
memset(buffer, 0, 1024);
}
getchar();
return 0;
}
备注:这个测试用例的目的在于,读取内存数据;