// uc_filemapping.h: interface for the UC_FILEMAPPING class.////#if !defined(AFX_UC_FILEMAPPING_H__72FE31B2_7B02_442F_A754_66427E1C5946__INCLUDED_)#define AFX_UC_FILEMAPPING_H__72FE31B2_7B02_442F_A754_66427E1C5946__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000//// 模块: 内存映射文件用户类// 作者: 张旻// 创建: 2002.01.16// 说明:// 利用内存映射文件进行进程之间的内存共享, // 目前的32位应用程序寻址范围4GB, 不需要高位//#include "uc_log.h"//自定义返回值#define RET_FILEOPENNED RET_USER + 1 //文件已经打开#define RET_FILENOTOPENNED RET_USER + 2 //文件未打开#define RET_BUFFERTOOBIG RET_USER + 3 //缓冲区过大#define RET_BUFFEROVERFLOW RET_USER + 4 //缓冲区溢出#define RET_FILEPROCESSING RET_USER + 5 //文件正在操作#define RET_OFFSETOVERFLOW RET_USER + 6 //偏移量溢出//共享内存的预留长度信息结构预定义typedef struct tagMapInfo{ DWORD dwSizeHigh; //高位文件大小 DWORD dwSizeLow; //低位文件大小 char szMappingName[_MAX_PATH]; //映射名称 tagMapInfo() { dwSizeHigh = dwSizeLow = 0; memset( szMappingName, 0, _MAX_PATH ); }}US_MAPINFO, *PUS_MAPINFO;//分页门限#define HIGH_MAX 0xFFFFFFFE //高位最大值#define LOW_MAX 0xFFFFFFFF - sizeof(US_MAPINFO) //低位最大值#define INFO_LEN sizeof(US_MAPINFO) //头信息长度#define NOPHYSICALFILE 0xFFFFFFFF //不需要物理文件class UC_FILEMAPPING : public UC_LOG {public: DWORD GetSize(); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 写入映射文件 // 参数: // [in] lpBuf 缓冲区 // [in] nSize 缓冲区大小 // [in] dwOffsetLow 偏移地址地位 // 返回: // RET_BADARG 参数非法 // RET_BUFFERTOBIG 缓存区过大 // RET_BUFFEROVERFLOW 缓冲区溢出 // RET_FILENOTOPENNED 文件未打开 // RET_FILEPROCESSING 文件正在操作 // RET_FILEERR 文件操作失败 // RET_OK 操作成功 // DWORD Write( LPVOID lpBuf, UINT &nSize, DWORD dwOffsetLow=0, BOOL isAppend=TRUE ); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 读取映射文件 // 参数: // [in] lpBuf 缓冲区 // [in] nSize 缓冲区大小 // [in] dwOffsetLow 偏移地址地位 // 返回: // RET_BADARG 参数非法 // RET_BUFFERTOBIG 缓存区过大 // RET_BUFFEROVERFLOW 缓冲区溢出 // RET_FILENOTOPENNED 文件未打开 // RET_FILEPROCESSING 文件正在操作 // RET_FILEERR 文件操作失败 // RET_OK 操作成功 // DWORD Read( LPVOID lpszBuf, UINT &nSize, DWORD dwOffsetLow=0 ); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 关闭映射文件 // 参数: // [in] wantDump 需要导出 // 返回: // RET_FILENOTOPENNED 文件未打开 // RET_FILEERR 文件操作失败 // RET_OK 操作成功 // DWORD Close( BOOL wantDump=TRUE ); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 打开映射文件 // 参数: // [in] lpszMappingName 映射内存命名 // 返回: // RET_BADARG 参数非法 // RET_FILEOPENNED 文件已经打开 // RET_FILEERR 文件操作失败 // RET_OK 操作成功 // DWORD Open( LPCTSTR lpszMappingName ); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 打开映射文件 // 参数: // [in] lpszFilePath 物理文件路径 // [in] lpszMappingName 映射内存命名 // [in] dwSizeLow 低位空间大小 // 返回: // RET_BADARG 参数非法 // RET_FILEOPENNED 文件已经打开 // RET_FILEERR 文件操作失败 // RET_OK 操作成功 // DWORD Open( LPCTSTR lpszFilePath, LPCTSTR lpszMappingName, DWORD dwSizeLow ); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 构造函数 // UC_FILEMAPPING(); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 析构函数 // virtual ~UC_FILEMAPPING();protected: HANDLE m_hPhysicsFile; //物理文件句柄 HANDLE m_hMappingFile; //映射文件句柄 HANDLE m_hFileOP; //文件操作互斥量 LPVOID m_lpCursor; //映射游标地址指针 LPVOID m_lpAddress; //映射文件地址指针 PUS_MAPINFO m_pusMapInfo; //映射内存头信息 BOOL m_isFileLoaded; //工作状态标志 BOOL m_isMyHandle; //是否是自己创建的文件映射 DWORD m_dwSysAlloc; //系统分配内存的最小单位private: DWORD FlushView(); DWORD GetErrorMessage(); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 格式化大小和偏移量 // 参数: // [in] dwOffsetLow 低位偏移量 // 返回: // RET_BADARG 参数非法 // RET_FILENOTOPENNED 文件未打开 // RET_FILEPROCESSING 文件正在操作 // RET_OK 操作成功 // // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 移动映射文件指针 // 参数: // [in] dwOffsetLow 低位偏移量 // 返回: // RET_BADARG 参数非法 // RET_FILENOTOPENNED 文件未打开 // RET_FILEPROCESSING 文件正在操作 // RET_OK 操作成功 //};#endif // !defined(AFX_UC_FILEMAPPING_H__72FE31B2_7B02_442F_A754_66427E1C5946__INCLUDED_)// uc_filemapping.cpp: implementation of the UC_FILEMAPPING class.////#include "stdafx.h"#include "uc_filemapping.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//// Construction/Destruction////构造函数UC_FILEMAPPING::UC_FILEMAPPING(){ WaitForSingleObject( m_hMutex, INFINITE ); //初始化句柄 m_hPhysicsFile = NULL; m_hMappingFile = NULL; m_hFileOP = NULL; //初始化标志 m_isFileLoaded = FALSE; m_isMyHandle = FALSE; //初始化文件成员变量 m_pusMapInfo = NULL; m_lpAddress = NULL; m_lpCursor = NULL; //得到系统的最小内存单位 SYSTEM_INFO SysInfo; GetSystemInfo( &SysInfo ); m_dwSysAlloc = SysInfo.dwAllocationGranularity; ReleaseMutex( m_hMutex );}//析构函数UC_FILEMAPPING::~UC_FILEMAPPING(){ WaitForSingleObject( m_hMutex, INFINITE ); //文件处理互斥操作 WaitForSingleObject( m_hFileOP, INFINITE ); //关闭映射内存头信息指针 if ( m_pusMapInfo ) delete m_pusMapInfo; //关闭句柄 ReleaseMutex( m_hFileOP ); //只有创建者才有权关闭句柄 if ( m_isMyHandle ){ CloseHandle( m_hPhysicsFile ); CloseHandle( m_hMappingFile ); CloseHandle( m_hFileOP ); } ReleaseMutex( m_hMutex );}//新建文件DWORD UC_FILEMAPPING::Open(LPCTSTR lpszFilePath, LPCTSTR lpszMappingName, DWORD dwSizeLow){ //状态监测 if ( m_isFileLoaded ) return RET_FILEOPENNED; //参数监测 if ( lpszMappingName==NULL ) return RET_BADARG; DWORD dwRet = RET_OK; //创建文件操作互斥句柄 char szMutex[_MAX_PATH]; memset( szMutex, 0, _MAX_PATH ); sprintf( szMutex, "%s_MUTEX", lpszMappingName ); m_hFileOP = CreateMutex( NULL, FALSE, szMutex ); WaitForSingleObject( m_hFileOP, INFINITE ); //创建对应的物理文件 if ( lpszFilePath!=NULL ){ //新建文件 m_hPhysicsFile = CreateFile( lpszFilePath, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); //如果文件存在, 打开现有文件 if ( m_hPhysicsFile==INVALID_HANDLE_VALUE ){ GetErrorMessage(); m_hPhysicsFile = CreateFile( lpszFilePath, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); } } if ( m_hPhysicsFile==INVALID_HANDLE_VALUE ){ GetErrorMessage(); m_hPhysicsFile = NULL; dwRet = RET_FILEERR; } else{ //创建映射文件(实际长度比申请长度多头信息的长度) if ( dwRet==RET_OK ){ if ( m_hPhysicsFile==NULL ){ m_hMappingFile = CreateFileMapping( (HANDLE)NOPHYSICALFILE, NULL, PAGE_READWRITE, 0, dwSizeLow, lpszMappingName ); } else{ m_hMappingFile = CreateFileMapping( m_hPhysicsFile, NULL, PAGE_READWRITE, 0, dwSizeLow + INFO_LEN, lpszMappingName ); } if ( m_hMappingFile==NULL ){ GetErrorMessage(); CloseHandle( m_hPhysicsFile ); m_hPhysicsFile = NULL; dwRet = RET_FILEERR; } else{ //获得对应的映射地址 m_lpAddress = MapViewOfFile( m_hMappingFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); if ( m_lpAddress==NULL ){ dwRet = RET_FILEERR; } else{ //保存映射内存头信息 if ( m_pusMapInfo==NULL ) m_pusMapInfo = new US_MAPINFO; m_pusMapInfo->dwSizeLow = dwSizeLow + INFO_LEN; memset( m_pusMapInfo->szMappingName, 0, _MAX_PATH ); memcpy( m_pusMapInfo->szMappingName, lpszMappingName, strlen(lpszMappingName) ); memcpy( m_lpAddress, m_pusMapInfo, INFO_LEN ); //保存申请获得的开始地址和初始化游标信息 //这里其实真正的其实地址因为包含了头部信 //息, 为此需要移动到空白部分 m_lpAddress = m_lpCursor = (LPVOID)( (LPBYTE)m_lpAddress + INFO_LEN ); //设置打开标志信息 m_isFileLoaded = TRUE; m_isMyHandle = TRUE; } } } } ReleaseMutex( m_hFileOP ); if ( dwRet!=RET_OK ) CloseHandle( m_hFileOP ); return dwRet;}//打开一个已有命名内存映射文件DWORD UC_FILEMAPPING::Open(LPCTSTR lpszMappingName){ //状态监测 if ( m_isFileLoaded || m_hFileOP ) return RET_FILEOPENNED; //参数监测 if ( lpszMappingName==NULL ) return RET_BADARG; DWORD dwRet = RET_OK; //创建文件操作互斥句柄 char szMutex[_MAX_PATH]; memset( szMutex, 0, _MAX_PATH ); sprintf( szMutex, "%s_MUTEX", lpszMappingName ); m_hFileOP = OpenMutex( MUTEX_ALL_ACCESS, FALSE, szMutex ); if ( m_hFileOP==NULL ){ return RET_FILENOTOPENNED; } WaitForSingleObject( m_hFileOP, INFINITE ); //打开映射文件 m_hMappingFile = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpszMappingName ); if ( m_hMappingFile==NULL ){ dwRet = RET_FILEERR; } else{ //获得对应的映射地址 m_lpAddress = MapViewOfFile( m_hMappingFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); if ( m_lpAddress==NULL ){ dwRet = RET_FILEERR; } else{ //获得映射内存头信息 if ( m_pusMapInfo==NULL ) m_pusMapInfo = new US_MAPINFO; memcpy( m_pusMapInfo, m_lpAddress, INFO_LEN ); //保存地址和游标 //同创建时候的原理 m_lpAddress = m_lpCursor = (LPVOID)( (LPBYTE)m_lpAddress + INFO_LEN ); //设置打开标志信息 m_isFileLoaded = TRUE; m_isMyHandle = TRUE; } } ReleaseMutex( m_hFileOP ); return dwRet;}//关闭文件DWORD UC_FILEMAPPING::Close(BOOL wantDump){ //状态监测 if ( m_isFileLoaded==FALSE ) return RET_FILENOTOPENNED; DWORD dwRet = RET_OK; WaitForSingleObject( m_hFileOP, INFINITE ); if ( wantDump ) FlushView(); delete m_pusMapInfo; m_pusMapInfo = NULL; m_isFileLoaded = FALSE; ReleaseMutex( m_hFileOP ); //只有创建者才有权利关闭句柄 if ( m_isMyHandle==FALSE ){ CloseHandle( m_hPhysicsFile ); CloseHandle( m_hMappingFile ); CloseHandle( m_hFileOP ); } return dwRet;}//读取映射文件DWORD UC_FILEMAPPING::Read(LPVOID lpBuf, UINT &nSize, DWORD dwOffsetLow ){ //状态监测 if ( m_isFileLoaded==FALSE ) return RET_FILENOTOPENNED; //参数监测 if ( lpBuf==NULL || nSize==0 ) return RET_BADARG; DWORD dwRet = RET_OK; WaitForSingleObject( m_hFileOP, INFINITE ); //计算内容是否溢出 UINT nSizeUsed = (UINT)( LPBYTE(m_lpCursor) - LPBYTE(m_lpAddress) ); if ( nSize<nSizeUsed ){ dwRet = RET_BUFFEROVERFLOW; } else{ //写入信息 nSize = nSizeUsed; memcpy( lpBuf, (LPVOID)( (LPBYTE)m_lpAddress + dwOffsetLow ), nSize ); } ReleaseMutex( m_hFileOP ); return dwRet;}//写入映射文件DWORD UC_FILEMAPPING::Write(LPVOID lpBuf, UINT &nSize, DWORD dwOffsetLow, BOOL isAppend ){ //状态监测 if ( m_isFileLoaded==FALSE ) return RET_FILENOTOPENNED; //参数监测 if ( lpBuf==NULL || nSize==0 ) return RET_BADARG; DWORD dwRet = RET_OK; WaitForSingleObject( m_hFileOP, INFINITE ); //计算内容是否溢出 UINT nLeftSize = (UINT)m_pusMapInfo->dwSizeLow - (UINT)( LPBYTE(m_lpCursor) - LPBYTE(m_lpAddress) ) - INFO_LEN; if ( nLeftSize<nSize ){ dwRet = RET_BUFFEROVERFLOW; } else{ //根据模式移动游标 if ( isAppend==FALSE ){ m_lpCursor = (LPVOID)( (LPBYTE)m_lpAddress + dwOffsetLow ); } //写入信息 memcpy( m_lpCursor, lpBuf, nSize ); //移动游标 if ( isAppend ) m_lpCursor = (LPVOID)( (LPBYTE)m_lpCursor + nSize ); } ReleaseMutex( m_hFileOP ); return dwRet;}//获得错误信息DWORD UC_FILEMAPPING::GetErrorMessage(){ DWORD dwRet = GetLastError(); LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRet, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Process any inserts in lpMsgBuf. // ... // Display the string. //MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); TRACE( "0xX: %s/n", dwRet, lpMsgBuf ); // Free the buffer. LocalFree( lpMsgBuf ); return dwRet;}//得到映射文件大小DWORD UC_FILEMAPPING::GetSize(){ if ( m_isFileLoaded==FALSE ) return RET_FILENOTOPENNED; if ( m_pusMapInfo ) return m_pusMapInfo->dwSizeLow - INFO_LEN; else return -1;}//输出内容DWORD UC_FILEMAPPING::FlushView(){ //状态监测 if ( m_isFileLoaded ){ if ( m_lpCursor > m_lpAddress && m_hPhysicsFile ){ SIZE_T nSize = (SIZE_T)( (LPBYTE)m_lpCursor - (LPBYTE)m_lpAddress ); if ( FlushViewOfFile( m_lpAddress, nSize ) ) return RET_OK; else return RET_FILEERR; } return RET_OK; } else{ return RET_FILENOTOPENNED; }}
希望各位同仁指正.