Windows进程间共享内存通信实例

抄抄补补整出来

采用内存映射文件实现WIN32进程间的通讯:Windows中的内存映射文件的机制为我们高效地操作文件提供了一种途径,它允许我们在WIN32进程中保留一段内存区域,把硬盘或页文件上的目标文件映射到这段虚拟内存中。注意:在程序实现中必须考虑各进程之间的同步问题。

在Windows操作系统下,任何一个进程不允许读取、写入或是修改另一个进程的数据(包括变量、对象和内存分配等),但是在某个进程内创建的文件映射对象的视图却能够为多个其他进程所映射,这些进程共享的是物理存储器的同一个页面。

因此,当一个进程将数据写入此共享文件映射对象的视图时,其他进程可以立即获取数据变更情况。

为了进一步提高数据交换的速度,还可以采用由系统页文件支持的内存映射文件而直接在内存区域使用,

显然这种共享内存的方式是完全可以满足在进程间进行大数据量数据快速传输任务要求的。

具体实现步骤如下: (http://www.jb51.net/article/52306.htm)

1、在服务器端进程中调用内存映射API函数CreateFileMapping创建一个有名字标识的共享内存;

函数CreateFileMapping原型如下:

2、在创建文件映射对象后,服务器端进程调用MapViewOfFile函数映射到本进程的地址空间内;

3、客户端进程访问共享内存对象,需要通过内存对象名调用OpenFileMapping函数,以获得共享内存对象的句柄

4、如果客户端进程获得共享内存对象的句柄成功,则调用MapViewOfFile函数来映射对象视图。用户可以使用该对象视图来进行数据读写操作,以达到数据通讯的目的。

5、当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:

FileMapping用于将存在于磁盘的文件放进一个进程的虚拟地址空间,并在该进程的虚拟地址空间中产生一个区域用于“存放”该文件,这个空间就叫做File View(存放在进程的虚拟内存中),系统并同时产生一个File Mapping Object(存放于物理内存中)用于维持这种映射关系,这样当多个进程需要读写那个文件的数据时,它们的File
View其实对应的都是同一个File Mapping Object,这样做可节省内存和保持数据的同步性,并达到数据共享的目的。

内存映射API函数CreateFileMapping创建一个有名的共享内存:
HANDLE
CreateFileMapping(
HANDLE hFile,                         // 映射文件的句柄,设为0xFFFFFFFF以创建一个进程间共享的对象
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,   // 安全属性
DWORD flProtect,                                                                   // 保护方式
DWORD dwMaximumSizeHigh,                                           //对象的大小 
DWORD dwMaximumSizeLow, 
LPCTSTR lpName                                                                 // 必须为映射文件命名
);

与虚拟内存类似,保护方式可以是PAGE_READONLY或是PAGE_READWRITE。如果多进程都对同一共享内存进行写访问,则必须保持相互间同步。映射文件还可以指定PAGE_WRITECOPY标志,可以保证其原始数据不会遭到破坏,同时允许其他进程在必要时自由的操作数据的拷贝。

在创建文件映射对象后使用可以调用MapViewOfFile函数映射到本进程的地址空间内。

下面说明创建一个名为MySharedMem的长度为4096字节的有名映射文件:

HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF),

NULL,PAGE_READWRITE,0,0x1000,"MySharedMem");
任何可以获得的物理文件句柄, 如果你需要创建一个物理文件无关的内存映射也无妨, 将它设置成为 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.

并映射缓存区视图:

LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,

FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);

其他进程访问共享对象,需要获得对象名并调用OpenFileMapping函数。

HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,

FALSE,"MySharedMem");

一旦其他进程获得映射对象的句柄,可以象创建进程那样调用MapViewOfFile函数来映射对象视图。用户可以使用该对象视图来进行数据读写操作,以达到数据通讯的目的。

当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:

if (!UnmapViewOfFile(pszMySharedMapView))

{

AfxMessageBox("could not unmap view of file");

}

要将文件中的数据映射到进程的虚拟内存中,你必须创建一个文件的视图。
    MapViewOfFile和MapViewOfFileEx函数使用CreateFileMapping返回的文件映射对象句柄来在进程的虚拟地址空间里建立文件的视图,或者文件的某个部分。如果这些函数指定的权限标志和CreateFileMapping中的权限标志不一致,则会执行失败。
    MapViewOfFile函数返回一个指向文件视图的指针。利用MapViewOfFile中声明的地址指针,程序就可以从文件中读以及向文件中写入数据。向文件视图中写入数据会导致文件映射对象改变。真正将数据写入到磁盘上的文件,由系统负责处理。数据并不是马上就别写到磁盘上,很多文件的输入输出都被缓存起来,以改善系统的性能。程序可以调用FlushViewOfFile函数来越过这个方式,强迫系统马上将数据写入到磁盘中去。

-----------------------------------------------------------------------------------

-----------------------------------------------------------------------------------

写一个创建共享内存,并写入数据

  1. #ifdef CHAR_TEST

  2.  

    char* pData = NULL;

  3.  

    #else

  4.  

    HWND* pData = NULL;

  5.  

  6.  

    #endif // CHAR_TEST

  7.  

  8.  

  9.  

    HANDLE hFileMap = NULL;

  10.  

    hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T("WndData"));

  11.  

    if (!hFileMap) // 不存在则创建

  12.  

    {

  13.  

    hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, _T("WndData"));

  14.  

    }

  15.  

  16.  

    if (hFileMap != NULL)

  17.  

    {

  18.  

    #ifdef CHAR_TEST

  19.  

    pData = (char*)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);

  20.  

    #else

  21.  

    pData = (HWND*)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);

  22.  

    #endif // CHAR_TEST

  23.  

  24.  

    if (pData == NULL)

  25.  

    {

  26.  

    CloseHandle(hFileMap);

  27.  

    hFileMap = NULL;

  28.  

    }

  29.  

    }

  30.  

  31.  

    HANDLE hMutex = CreateMutex(NULL, TRUE, _T("WndMutex"));

  32.  

  33.  

    #ifdef CHAR_TEST

  34.  

    char* strValue = "123abcpStr";

  35.  

    //pData = strValue;

  36.  

    memcpy(pData, strValue, strlen(strValue));

  37.  

  38.  

    #else

  39.  

    CStatic* pStcPic = (CStatic*)GetDlgItem(IDC_STC_PIC);

  40.  

    HWND hWnd = pStcPic->m_hWnd;

  41.  

    //pData = &hWnd;

  42.  

    memcpy(pData, &hWnd, sizeof(HWND*));

  43.  

    #endif // char_te

  44.  

  45.  

  46.  

    //FlushViewOfFile(pData, sizeof(HWND*));

  47.  

  48.  

    ReleaseMutex(hMutex);

-----------------------------------------------------------------------------------

读取共享数据:

  1. HANDLE hMutex = NULL;

  2.  

    while (true)

  3.  

    {

  4.  

    hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("WndMutex"));

  5.  

    if (NULL != hMutex)

  6.  

    {

  7.  

    break;

  8.  

    }

  9.  

    Sleep(200);

  10.  

    }

  11.  

  12.  

    WaitForSingleObject(hMutex, INFINITE);

  13.  

  14.  

    HANDLE hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T("WndData"));

  15.  

    ASSERT(hFileMap);

  16.  

  17.  

    #if 1

  18.  

    HWND* pData = (HWND*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);

  19.  

    HWND hGet = *pData;

  20.  

    #else

  21.  

    char* pData = (char*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 1024);

  22.  

    char* strTemp = pData;

  23.  

    AfxMessageBox(strTemp);

  24.  

    #endif

  25.  

  26.  

    HDC dc = ::GetDC(hGet);

  27.  

  28.  

    UnmapViewOfFile(pData);

  29.  

  30.  

    ReleaseMutex(hMutex);


 在向共享内存写值的时候,char* strValue = "123abcpStr";

再赋给 pData = strValue; 在读取的时候会读不到数据!

一定要用内存烤贝:memcpy(pData, strValue, strlen(strValue));

jpg 改 rar 

原文地址:https://www.cnblogs.com/kuangke/p/9397691.html

时间: 2024-07-29 03:44:45

Windows进程间共享内存通信实例的相关文章

Windows环境下共享内存通信

一.引言 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换. 进程间通讯(即:同机通讯)和数据交换有多种方式:消息.共享内存.匿名(命名)管道.邮槽.Windows套接字等多种技术."共享内存"(shared memory)可以定义为对一个以上的进程是可见的内存或存在于多个进程的虚拟地址空间.例如:如果两个进程使用相同的DLL,只把DLL的代码页装入内存

C# 进程间共享内存通信方式

从别处看到一篇文章做进程间通信很好使,唯一的问题是,需要注意using的用法,Using有个用法3, using 语句允许程序员指定使用资源的对象应当何时释放资源.using 语句中使用的对象必须实现 IDisposable 接口.此接口提供了 Dispose 方法,该方法将释放此对象的资源. ①可以在 using 语句之中声明对象.     Font font2 = new Font("Arial", 10.0f);     using (font2)     {         /

Linux 进程间共享内存 SYSTEMV

#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int shmflag) key取值为IPC_PRIVATE时,shmflag应为IPC_CREAT,则新建共享内存key取值不为IPC_PRIVATE则应为已创建的key值,shmflag不应包含IPC_CREAT和IPC_EXCL,且大小小于等于原共享内存大小成功则返回共享内存id,失败返回-1 void *shmat(int sh

linux 进程间共享内存示例

写入端: #include <iostream> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/shm.h> using namespace std; struct MappingDataType { int mappingData; }; bool SetUsedPID(string mappingName) { void *shm = NULL

windows进程间通讯的方法

版权声明 请尊重原创作品.转载请保持文章完整性,并以超链接形式注明原始作者“tingsking18”和主站点地址,方便其他朋友提问和指正.   1.使用共享内存 代码如下: [cpp] view plaincopy void FileMapping(void) { //打开共享的文件对象. m_hMapFile = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,_T("TestFileMap")); if (m_hMapFile) { //显

windows核心编程之进程间共享数据

有时候我们会遇到window进程间共享数据的需求,例如说我想知道系统当前有多少某个进程的实例. 我们能够在程序中定义一个全局变量.初始化为0.每当程序启动后就加1.当然我们我们能够借助第三方介质来储存这个变量,然后解析. 这样做必须做到先写入后解析.不能实时更新数据.假设不考虑其它储存介质.仅仅是进程中的通信,应该怎么做呢?windows提供了一些可行的方法,以下介绍经常使用的两种. 一.共享数据段 #include "stdafx.h" #include <Windows.h&

利用内存映射文件在两个进程间共享数据 转

private hMapFile: THandle; MapFilePointer: Pointer; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin hMapFile := CreateFileMapping ( $FFFFFFFF, // 特殊内存映射句柄 nil, page_

Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6666491 在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了它是如何辅助内存管理系统来有效地管理内存的,在再前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Share

父子进程共享内存通信的三种方法

1.  mmap MAP_ANONYMOUS 在支持MAP_ANONYMOUS的系统上,直接用匿名共享内存即可, 2. mmap  /dev/zero 有些系统不支持匿名内存映射,则可以使用fopen打开/dev/zero文件,然后对该文件进行映射,可以同样达到匿名内存映射的效果. 3. shmget shmat shmctl shmget 是老式的system V 共享内存模式,很多系统都支持这种方法. 父子进程共享内存通信的三种方法