一个内存文件映射用户类

    技术2022-05-11  165

    // 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;    }}

     

    希望各位同仁指正.


    最新回复(0)