CSDN博客

img rick1126

FileMapping用户类源代码(原创, 欢迎批评指正)

发表于2002/1/22 11:34:00  745人阅读

欢迎指正

// 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_FILE
static 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( "0x%08X: %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;
 }
}

0 0

相关博文

我的热门文章

img
取 消
img