多进程间通讯,是应用程序间常用的一种方式,今天简单的介绍的介绍一下利用文件映射进行进程间通讯。
一.原理介绍
每一个进程由两部分组成 1. 进程内核对象,2. 进程内存地址空间。不同的进程器地址空间相互隔离,无法相互访问,因此进程间通信变得十分困难。
FileMapping内核对象将将其与制定的一段内存映射到一起,在不同的进程打开FileMapping对象,获得其与其相关联的内存,可实现双方同时对与其关联的内存读写(需权限支持,注意不同进程间的同步操作)从而实现进程间的通讯
HANDLE CreateFileMapping(
HANDLE hFile, //需要映射的文件,若不是对文件映射填写INVALID_HANDLE_VALUE
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
// 安全属性
DWORD flProtect, // 访问方式
DWORD dwMaximumSizeHigh, // high-order 32 bits of object size
DWORD dwMaximumSizeLow, // low-order 32 bits of object size
LPCTSTR lpName // 内核名称,供不同进程访问
);
HANDLE OpenFileMapping( DWORD dwDesiredAccess, // 访问方式
BOOL bInheritHandle, // 继承表示
LPCTSTR lpName // 内核名称
);
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 文件映射句柄
DWORD dwDesiredAccess, // 访问方式
DWORD dwFileOffsetHigh, // high-order 32 bits of file offset
DWORD dwFileOffsetLow, // low-order 32 bits of file offset
DWORD dwNumberOfBytesToMap //映射缓存大小
);
下面通过一个具体事例说明一下
进程一,父进程
#include <iostream>
#include <windows.h>
#include <tchar.h>
using namespace std;
TCHAR g_szFileMapName[] = _T("MyFileMappingObject");
TCHAR g_szEventName[] = _T("MyEvent");
#define BUF_SIZE 4096
int main()
{
HANDLE hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL, PAGE_READWRITE,
0, BUF_SIZE, g_szFileMapName);
if (!hFileMap)
{
cout << "Create FileMapping Error : " << GetLastError()<<endl;
CloseHandle(hFileMap);
return 0;
}
HANDLE hEvent = CreateEvent(NULL, false, false, g_szEventName);
if (!hEvent)
{
cout << "Create FileMapping Error : " << GetLastError() << endl;
CloseHandle(hFileMap);
CloseHandle(hEvent);
return 0;
}
LPCTSTR lpBuf = (LPCTSTR)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS,
0, 0, BUF_SIZE);
if (!lpBuf)
{
CloseHandle(hFileMap);
CloseHandle(hEvent);
return -1;
}
/*
创建接收线程
*/
//1. 启动结构
STARTUPINFO si = { sizeof(si) };
SECURITY_ATTRIBUTES saProcess, saThread;
PROCESS_INFORMATION piProcess, piThread;
saProcess.nLength = sizeof(saProcess);
saProcess.lpSecurityDescriptor = NULL;
saProcess.bInheritHandle = true;
saThread.nLength = sizeof(saThread);
saThread.lpSecurityDescriptor = NULL;
saThread.bInheritHandle = false;
TCHAR szApp[MAX_PATH] = _T("../Debug/Process2.exe");
TCHAR szPath[MAX_PATH] = _T("");
if (!CreateProcess(szApp, szPath, &saProcess, &saThread, true, CREATE_NEW_CONSOLE, NULL, NULL, &si, &piProcess))
{
cout << "Create Process Error" << GetLastError()<<endl;
return -1;
}
//AllocConsole();
TCHAR szBuf[4096] = _T("");
while (true)
{
ResetEvent(hEvent);
wcout << _T(">");
wcin>> szBuf;
if (!wcscmp(szBuf, _T("Exit")))
{
break;
}
wcscpy((TCHAR*)lpBuf, szBuf);
SetEvent(hEvent);
Sleep(50);
}
UnmapViewOfFile(lpBuf);
CloseHandle(hFileMap);
CloseHandle(hEvent);
return 0;
}
进程二 子进程
// Process2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <Windows.h>
#include <tchar.h>
TCHAR g_szFileMapName[] = _T("MyFileMappingObject");
TCHAR g_szEventName[] = _T("MyEvent");
#define BUF_SIZE 4096
int main()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,
FALSE,
g_szFileMapName);
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d). \n"),
GetLastError());
return 1;
}
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, true, g_szEventName);
if (!hEvent)
{
cout << "Open Event Error : " << GetLastError() << endl;
CloseHandle(hMapFile);
CloseHandle(hEvent);
return 0;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
while (true)
{
WaitForSingleObject(hEvent, INFINITE);
wcout << pBuf << endl;
// MessageBox(NULL, pBuf, L"显示", MB_OK);
}
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}