在项目工程中需要64位程序调用32位程序并加以通信。 实现了两个进程间的内存共享。
提示:以下是本篇文章正文内容,下面案例可供参考
1、进程间通信原理:
主要实现:
• 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。
• 可以使用内存映射文件来访问磁盘上的数据文件。这使你可以不必对文件执行I/O操作,并且可以不必对文件内容进行缓存。
• 可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。Windows确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上的多个进程互相进行通信的最有效的方法。
2、使用到的API
typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId; //为了兼容而保留的已过时成员。
struct {
WORD wProcessorArchitecture;
WORD wReserved;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
DWORD dwPageSize; //页面大小和页面保护和承诺的粒度。这是VirtualAlloc函数使用的页面大小
LPVOID lpMinimumApplicationAddress;//指向应用程序和动态链接库可访问的·最低·内存地址的指针,(DLL)
LPVOID lpMaximumApplicationAddress; //指向应用程序和DLL可访问的·最高·内存地址的指学针
DWORD_PTR dwActiveProcessorMask; //一个掩码,表示配置未系统中的处理器集。位0时处理器0;位31时处理器31
DWORD dwNumberOfProcessors; //当前组中的逻辑处理器数。
DWORD dwProcessorType; //处理器类型
DWORD dwAllocationGranularity; //可在其中分配虚拟内存的起始地址的粒度。
WORD wProcessorLevel; //依赖于体系结构的处理器级别。它应仅用于显示目的。
WORD wProcessorRevision;//依赖于体系结构的处理器修订版本。
} SYSTEM_INFO, *LPSYSTEM_INFO; //系统用信息
SYSTEM_INFO结构 ——sysinfoapi.h
1、GetSystemInfo
参数 | 功能 |
---|---|
[out] LPSYSTEM_INFO lpSystemInfo | 指向接受信息的SYSTEM_INFOj结构的指针 |
2、HANDLE CreateFileMapping( HANDLE hFile,LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName );
—创建共享内存
参数 | 功能 |
---|---|
HANDLE | 物理文件句柄,返回值 |
HANDLE hFile | 物理文件句柄 |
LPSECURITY_ATTRIBUTES lpAttributes | 安全设置(一般位NULL) |
DWORD dwMaximumSizeHigh | 高位文件大小 |
DWORD dwMaximumSizeLow | 低位文件大小 |
LPCTSTR lpName | 共享内存名称 |
3、HANDLE OpenFileMapping(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );
--打开一个又名的共享内存
参数 | 功能 |
---|---|
HANDLE | [返回值]成功打开lpName名字的共享内存地址;失败,返回NULL |
DWORD dwDesiredAccess | 通道模式 |
BOOL bInheritHandle | 继承标志位 |
LPCTSTR lpName | 文件映射目标的名称指针 |
4、LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap);
--映射共享内存地址空间
参数 | 介绍 |
---|---|
LPVOID | [返回]成功:映射的地址;失败:NULL |
HANDLE hFileMappingObject | 文件映射目标到映射到地址空间 |
DWORD dwDesiredAccess | 存取模式 |
DWORD dwFileOffsetHigh | 高阶 32 位文件偏移量 |
DWORD dwFileOffsetLow | 低阶32位文件偏移量 |
DWORD dwNumberOfBytesToMap | 映射字节位数 |
5、BOOL UnmapViewOfFile( LPCVOID lpBaseAddress );
--解除映射
参数 | 介绍 |
---|---|
BOOL | [返回] 成功:非0; 失败:0; |
LPCVOID lpBaseAddress | 映射地址起始位置, MapViewOfFile 的句柄 |
6、BOOL CloseHandle(HANDLE hObject)
--关闭打开的句柄
参数 | 介绍 |
---|---|
BOOL | [返回]成功:true;失败:false; |
HANDLE hObject | 要关闭的目标句柄 |
二、信号量:
在另个进程访问共享内存时,会造成数据访问冲突。需要使用信号量来限制该访问顺序。
1、CreateSemaphore 创建信号量对象
HANDLE WINAPI CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,
LONG lMaximumCount,LPCTSTR lpName);
参数 | 介绍 |
---|---|
HANDLE | [返回]成功:返回信号量句柄;失败:NULL; |
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, | 设置安全属性 |
LONG lInitialCount | 初始的计数值 |
LONG lMaximumCount | 最大的计数值 |
LPCTSTR lpName | 对信号量对象命名 |
2、OpenSemaphore 通过信号量名,获得信号量对象句柄
HANDLE WINAPI OpenSemaphore(DWORD dwDesireAccess,BOOL bInheritHandle,LPCTSTR lpName);
参数 | 介绍 |
---|---|
HANDLE | [返回]成功:返回信号量句柄;失败:NULL; |
DWORD dwDesireAccess | -SEMAPHORE_ALL_ACCESS- |
BOOL bInheritHandle | 是否继承 |
LPCTSTR lpName | 信号量名称 |
3、ReleaseSemaphore释放信号量
BOOL WINAPI ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount,LPLONG lpPreviousCount);
参数 | 介绍 |
---|---|
BOOL | [返回]成功:true;失败:false; |
HANDLE hSemaphore | 信号量句柄 |
LONG lReleaseCount | 可以释放多个计数 |
LPLONG lpPreviousCount | 上一个计数 |
4、WaitForSingleObject 等待指定对象处于信号状态或超时间隔已过
DWORD WaitForSingleObject( [in] HANDLE hHandle, [in] DWORD dwMilliseconds)
参数 | 介绍 |
---|---|
DWORD | [返回]成功,则返回值指示导致函数返回的事件。失败:返回错误代码 |
[in] HANDLE hHandle | 对象的句柄 |
[in] DWORD dwMilliseconds | 超时间隔(以毫秒为单位) |
函数检查指定对象的当前状态。 如果对象的状态未对齐,则调用线程将进入等待状态,直到发出该对象信号或超时间隔。
该函数修改某些类型的同步对象的状态。 修改仅适用于指示状态导致函数返回的对象。 例如,信号灯对象的计数减少一个。
三、从内存中取值
1、CopyMemory 拷贝内存数据
void CopyMemory( In PVOID Destination, In const VOID *Source, In SIZE_T Length);
参数 | 介绍 |
---|---|
void | [返回]成功:true;失败:false; |
Destination | A pointer to the starting address of the copied block’s destination. |
Source | A pointer to the starting address of the block of memory to copy. |
Length | The size of the block of memory to copy, in bytes. |
如果源块和目标块重叠,则结果未定义。对于重叠块,请使用MoveMemory函数。
2、MoveMemory 拷贝内存数据
void MoveMemory( In PVOID Destination, In const VOID *Source, In SIZE_T Length);
参数 | 介绍 |
---|---|
void | [返回]成功:true;失败:false; |
Destination | A pointer to the starting address of the move destination. |
Source | A pointer to the starting address of the block of memory to be moved. |
Length | The size of the block of memory to move, in bytes. |
This function is defined as the RtlMoveMemory function. Its implementation is provided inline. The source and destination blocks may overlap.
结论:
操纵同一块内存地址。
Server服务器:
void SharedMemory()
{
HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
256,
TEXT("MySharedMemory")
);
LPBYTE pcMap = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS,
0, 0, 0);
char *pSharedStr = "0this is my shared memory";
memcpy(pcMap, pSharedStr, strlen(pSharedStr));
while (pcMap[0] == '0')
{
Sleep(100);
}
// 释放内存
UnmapViewOfFile(pcMap);
CloseHandle(hFileMapping);
}
Client 客户端
void TestSharedMemory()
{
HANDLE hFileMapping;
LPBYTE pcMap;
hFileMapping = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, TEXT("MySharedMemory"));
if(hFileMapping == NULL)
{
return;
}
pcMap = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS,
0, 0, 0);
cout << pcMap << endl;
// 通知主程序释放
pcMap[0] = '1';
// 释放内存
UnmapViewOfFile(pcMap);
CloseHandle(hFileMapping);
}
这次先写到这里,例子下次再写。