欢迎指正
// 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; //低位文件大小
DWORD dwSizeUsedHigh; //高位使用大小 DWORD dwSizeUsedLow; //低位使用大小
char szMappingName[_MAX_PATH]; //映射名称
tagMapInfo() { dwSizeHigh = dwSizeLow = dwSizeUsedHigh = dwSizeUsedLow = 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: // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 获得文件使用大小 // 参数: // 返回: // 文件使用大小 // DWORD GetSizeUsed(); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 获得文件大小 // 参数: // 返回: // 文件大小 // DWORD GetSize(); // // 作者: 张旻 // 创建: 2002.01.16 // 功能: 写入映射文件 // 参数: // [in] lpBuf 缓冲区 // [in] nSize 缓冲区大小 // [in] dwOffsetLow 偏移地址地位 // [in] isAppend 追加写入 // 返回: // 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 );
//记录文件使用情况 m_pusMapInfo->dwSizeUsedLow = (DWORD)( (LPBYTE)m_lpCursor - (LPBYTE)m_lpAddress ); }
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::GetSizeUsed(){ if ( m_isFileLoaded==FALSE ) return RET_FILENOTOPENNED;
if ( m_pusMapInfo ) return m_pusMapInfo->dwSizeUsedLow; 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; }}