用文件映射(File Mapping)实现进程间内存共享

本文介绍如何使用文件映射(FileMapping)和互斥量(Mutex)实现进程间内存共享,并提供了创建、释放共享内存及读写操作的具体函数实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引用自:http://blog.youkuaiyun.com/starlee/archive/2007/06/01/1633762.aspx
  我们知道,在Windows中的每个进程都有自己独立的内存空间。该独立的内存空间包含了所有的可执行模块或DLL模块的代码和数据以及动态内存分配的空间。每个进程的内存空间只能被该进程访问,其他进程是不能访问的。
    如果我们要想在进程间共享内存(也就是创建一块不同进程都能访问的内存),那就必须使用内核对象。因为内核对象由Windows系统内核所拥有,而不是由进程所拥有。
    下面就用文件映射(File Mapping)和互斥量(Mutex)两中内核对象来实现简单的进程间内存共享。文件映射(File Mapping)用来开辟共享的内存空间,而互斥量(Mutex)则是用来使读写互斥。 Windows,实际上只有映像文件共享内存一种。
    在该例子里,实现了下面5个函数用来进行进程间的内存共享。可以把这5个函数放到一个DLL里面当成输出函数来用。在进程里加载该DLL并调用相应的函数就可实现进程间内存共享。
    首先,定义返回值代码:
typedef enum
{
    LX_OK                                = 0, // 正常返回
    LX_SHAREDMEMORY_EXISTS  = 1, // 共享内存已经存在
    LX_INVALID_SHAREDMEMORY = 2, // 共享内存错误返回
    LX_INVALID_SIZE                 = 3  // 共享内存大小错误
}LX_RETURN_VALUE;    然后,是函数声明:
// 创建共享内存
LX_RETURN_VALUE CreateSharedMemory(UINT nSize);
// 释放共享内存
LX_RETURN_VALUE ReleaseSharedMemory();
// 得到共享内存大小
LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize);
// 向共享内存写入数据
LX_RETURN_VALUE WriteToSharedMemory(void *pData, UINT nSize);
// 从共享内存读取数据
LX_RETURN_VALUE ReadFromSharedMemory(void *pData, UINT nSize);    下面是函数的实现:
// 互斥量
CMutex g_mMutex(FALSE, "StarLeeMutex");

LX_RETURN_VALUE CreateSharedMemory(UINT nSize)
{
    // 创建共享内存块
    HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nSize, "StarLeeSharedMemory");

    // 创建错误
    if ((hFileMapping == NULL) || (hFileMapping == INVALID_HANDLE_VALUE))
        return LX_INVALID_SHAREDMEMORY;

    // 共享内存已经存在
    if (GetLastError() == ERROR_ALREADY_EXISTS)
        return LX_SHAREDMEMORY_EXISTS;

    // 创建另外一块内存存放共享内存的大小
    HANDLE hSize = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, sizeof(UINT), "StarLeeSharedMemorySize");

    if ((hSize == NULL) || (hSize == INVALID_HANDLE_VALUE) || (GetLastError() == ERROR_ALREADY_EXISTS))
        return LX_INVALID_SHAREDMEMORY;

    // 得到存放共享内存大小的指针
    UINT *pSize = (UINT *)MapViewOfFile(hSize, FILE_MAP_WRITE, 0, 0, sizeof(UINT));

    if (pSize == NULL)
        return LX_INVALID_SHAREDMEMORY;

    // 写入共享内存的大小
    memcpy(pSize, &nSize, sizeof(UINT));

    UnmapViewOfFile(pSize);

    return LX_OK;
}

LX_RETURN_VALUE ReleaseSharedMemory()
{
    g_mMutex.Lock();

    // 打开共享内存
    HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "StarLeeSharedMemory");

    // 关闭共享内存
    if (hFileMapping != NULL)
        CloseHandle(hFileMapping);

    // 打开存放共享内存大小的文件映射
    HANDLE hSize = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "StarLeeSharedMemorySize");

    // 关闭存放共享内存大小的文件映射
    if (hSize != NULL)
        CloseHandle(hSize);

    g_mMutex.Unlock();

    return LX_OK;
}

LX_RETURN_VALUE GetSharedMemorySize(UINT& nSize)
{
    g_mMutex.Lock();

    HANDLE hSize = OpenFileMapping(FILE_MAP_READ, FALSE, "StarLeeSharedMemorySize");

    if (hSize == NULL)
    {
        g_mMutex.Unlock();

        return LX_INVALID_SHAREDMEMORY;
    }

    UINT *pSize = (UINT *)MapViewOfFile(hSize, FILE_MAP_READ, 0, 0, sizeof(UINT));

    if (pSize == NULL)
    {
        g_mMutex.Unlock();

        return LX_INVALID_SHAREDMEMORY;
    }

    // 得到共享内存的大小
    memcpy(&nSize, pSize, sizeof(UINT));

    g_mMutex.Unlock();

    return LX_OK;
}

LX_RETURN_VALUE WriteToSharedMemory(void *pDate, UINT nSize)
{
    g_mMutex.Lock();

    UINT nSharedMemorySize = 0;

    // 得到共享内存的大小
    if (GetSharedMemorySize(nSharedMemorySize) != LX_OK)
        return LX_INVALID_SHAREDMEMORY;

    // 检查共享内存的大小
    if (nSize > nSharedMemorySize)
        return LX_INVALID_SIZE;

    HANDLE hFileMapping = OpenFileMapping(FILE_MAP_WRITE, FALSE, "StarLeeSharedMemory");

    if (hFileMapping == NULL)
    {
        g_mMutex.Unlock();

        return LX_INVALID_SHAREDMEMORY;
    }

    void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, nSize);

    if (pMapView == NULL)
    {
        g_mMutex.Unlock();

        return LX_INVALID_SHAREDMEMORY;
    }

    // 将数据写入共享内存
    memcpy(pMapView, pDate, nSize);

    UnmapViewOfFile(pMapView);

    g_mMutex.Unlock();

    return LX_OK;
}

LX_RETURN_VALUE ReadFromSharedMemory(void *pData, UINT nSize)
{
    g_mMutex.Lock();

    UINT nSharedMemorySize = 0;

    if (GetSharedMemorySize(nSharedMemorySize) != LX_OK)
        return LX_INVALID_SHAREDMEMORY;

    if (nSize > nSharedMemorySize)
        return LX_INVALID_SIZE;

    HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE, "StarLeeSharedMemory");

    if (hFileMapping == NULL)
    {
        g_mMutex.Unlock();

        return LX_INVALID_SHAREDMEMORY;
    }

    void *pMapView = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, nSize);

    if (pMapView == NULL)
    {
        g_mMutex.Unlock();

        return LX_INVALID_SHAREDMEMORY;
    }   

    // 从共享内存读取数据
    memcpy(pData, pMapView, nSize);

    UnmapViewOfFile(pMapView);

    g_mMutex.Unlock();

    return LX_OK;
}
用到的主要接口有:


The CreateFileMapping function creates or opens a named or unnamed file mapping object for the specified file.

HANDLE CreateFileMapping(  HANDLE hFile,  LPSECURITY_ATTRIBUTES lpAttributes,  DWORD flProtect,  DWORD dwMaximumSizeHigh,  DWORD dwMaximumSizeLow,  LPCTSTR lpName);The MapViewOfFile function maps a view of a file into the address space of the calling process.

To specify a suggested base address, use the MapViewOfFileEx function.

LPVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap );
 


The OpenFileMapping function opens a named file mapping object.

HANDLE OpenFileMapping(  DWORD dwDesiredAccess,  BOOL bInheritHandle,  LPCTSTR lpName);

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/ruixj/archive/2007/06/05/1639555.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值