下面用共享映射文件的方式实现进程间通信,代码可以运行。

一、浅理解
每个进程有自己独立的空间,一个进程无法访问其他进程的数据。就好像两个是互不干涉的个体,想让它们进行通信(交换数据),就必须有一段它们都可以访问到的空间,作为中间介质。在计算机中,可以存放数据的地方分为内存和硬盘,进程是运行着的程序,肯定在内存当中。为让进程A和进程B进行通信,它们都可以访问的空间可以是

内存中它们以外的区域
硬盘中的区域
内存文件映射是将硬盘中的一个文件映射到内存中,进程A,B都可以访问该内存(文件),达到交换数据的目的。如右图是给用户的直接感觉,两个进程操作同一个物理文件,通过文件的读写,交换数据。

二、发送方(服务器)
个人理解,虽然共享内存都可以读写,也没有服务器和客户端的概念。但是,需要有一方创建这个文件,而另一方只需要获取并打开这个文件。为了方便,将创建文件的一方称作服务器,而获取并打开文件的一方称为客户端。而事实上,服务器或者客户端都可以对文件进行读写,类似于网络编程中的客户端和服务器都可以发消息接消息。自己写的服务器端C++代码如下

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#pragma warning(disable:4996)
int_tmain(intargc, _TCHAR* argv[]){
    HANDLEhFile =CreateFile(TEXT("c:\zj.dat"),GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==NULL){
        printf("create file error!");
        return0;
    }
    // HANDLE hFile = (HANDLE)0xffffffff; //创建一个进程间共享的对象
    HANDLEhMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,  0,1024*1024,TEXT("ZJ"));
    intrst = GetLastError();
    if(hMap != NULL && rst == ERROR_ALREADY_EXISTS){
        printf("hMap error\n");
        CloseHandle(hMap);
        hMap = NULL;
        return0;
    }
    CHAR* pszText=NULL;
    pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,1024*1024);
    if(pszText==NULL){
        printf("view map error!");
        return0;
    }
    sprintf(pszText,"hello my first mapping file!\n"); //其实是向文件中(共享内存中)写入了
    while(1){
        printf(pszText);
        Sleep(3000);
    }
    getchar();
    UnmapViewOfFile((LPCVOID)pszText);
    CloseHandle(hMap);
    CloseHandle(hFile);
    return0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
当调用 CreateFileMapping 创建命名的内存映射文件对象时 , Windows 即在物理内存申请一块指定大小的内存区域 , 返回文件映射对象的句柄 hMap ; 为了能够访问这块内存区域必须调用 MapViewOfFile 函数 , 促使 Windows 将此内存空间映射到进程的地址空间中 ; 当在其他进程访问这块内存区域时 , 则必须使用 OpenFileMapping 函数取得对象句柄 hMap , 并调用 MapViewOfFile 函数得到此内存空间的一个映射 , 这样系统就把同一块内存区域映射到了不同进程的地址空间中 , 从而达到共享内存的目的 。

先创建一个文件 CreateFile
HANDLE hFile = CreateFile(...);
参数可参见MSDN,就是创建一般的文件,此处不详说。个人认为这个文件的目的,就是共享内存的实体(也就是对应的硬盘中的区域)。
CreateFile(TEXT("c:\zj.dat"),GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
     在C盘的确有文件zj.dat 该文件名可以随意取。
创建内存映射文件 CreateFileMapping
    将上述硬盘中的文件hFile映射成为一个虚拟的映射文件 hMap ,即将物理文件与虚拟文件绑定,或者理解成将硬盘中的文件映射到内存当中。
HANDLE hMap = CreateFileMapping( hFile, NULL, PAGE_READWRITE, 0,1024*1024,TEXT("ZJ"));
     参数解释: hFile是对应的物理文件的句柄。如果hFile=NULL,即没有通过CreateFile创建一个实际存在的文件。有解释为创建一个进程间共享的对象。个人认为也可能是在内存中随机开辟了一段空间,或者在硬盘上有一个默认文件。
NULL: 安全属性
PAGE_READWRITE: 可读可写
0, 1024*1024: 从物理文件的高0位到低,1024*1024为映射成虚拟文件。(个人是这样理解的)
ZJ :是虚拟文件的名字/标识,客户端读时也用此来作为文件的标识,所以,这个名字应该是在进程外部注册的。
加载并获得内存映射文件 MapViewOfFile 在内存中的地址
     将虚拟文件映射成内存地址,方便使用。即将文件与内存绑定,以后由此地址访问该块内存。
CHAR* pszText=NULL; //一个指针,不需要分配空间
pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,1024*1024); //通过映射后,该指针就指向该文件,如果最后一个参数是0表示映射整个文件。
    参数解释:hMap作为虚拟文件的标识(通俗点就是虚拟文件名);
FILE_MAP_ALL_ACCESS:设定访问模式;
0,0:从虚拟文件的哪个位置开始映射成内存
1024*1024: 映射的内存大小
使用内存,即使用文件
    可以向这个内存(文件)读写数据了。
//写:
sprintf(pszText,"hello my first mapping file!\n");
    语句本身的意思,是将句子写入字符串pszText中,而这个字符串并没有在程序中分配空间,即没有new。但这句话也不会报错。是因为该字符串地址指向了映射文件,即通过操作该指针,实际是操作了文件,句子写入了文件当中。
//读:
printf(pszText);
    语句本身是将字符串中的内容输出到屏幕上,该字符串中没有分配空间,也没有赋值。但通过映射为文件,可以将文件中的内容通过该指针输出到屏幕上。
     注:个人理解,可以认为该指针pszText直接指向了硬盘空间(即通过内存文件和硬盘文件直接联系在一起)。就是文件的操作符。
5. 载映射 :
UnmapViewOfFile((LPCVOID)pszText);//卸载映射
6. 关闭文件:
"__mceDel">CloseHandle(hMap); //关闭虚拟文件
"__mceDel">CloseHandle(hMap); //关闭虚拟文件
三、接收方(客户端)
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,TRUE,TEXT("ZJ"));  
if(hMap == NULL){        
printf("open file map error!");
return0;
}    
CHAR* pszText = NULL;    
pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,1024*1024);    if(pszText==NULL){        
printf("map view error!\n");        
return0;    
}    
printf(pszText); //从文件中读(共享内存)         
sprintf(pszText,"second data!\n"); //写入    
getchar();    
UnmapViewOfFile(pszText);    
CloseHandle(hMap);    
hMap = NULL;     
return0;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
打开内存映射文件(虚拟文件)
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,TRUE,TEXT("ZJ"));
通过内存映射文件名 ZJ 找到该文件的。
获得地址
CHAR* pszText = NULL;
pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,1024*1024);
    映射成内存 MapViewOfFile和服务器中的一样。
使用内存
printf(pszText); //从文件中读(共享内存)
    读写数据,此处写入数据后,从服务器中读出来的内容就改变了。
    可以证明,服务器客户端同时使用着同一个文件,文件是它们之间的一个通道,用来交换数据
关闭映射,关闭文件。同服务器
UnmapViewOfFile(pszText);
CloseHandle(hMap);
四、注意点
服务器和客户端必须同时为进程,即都在运行的时候,才可以交换数据。
    虽然是通过物理文件,交互数据的,但是ZJ是虚拟文件的名字,该名字必须在两个进程中都能认识,才可以通过它来交互数据。
     所以,如果服务器先打开,写入文件后,关闭。 客户端,再打开文件,则CreateFileMap会失败,也无法进行文件映射了。就像网络通信一样,必须双方都在,才可以通信。
当然客户端也可以通过CreateFile打开一个存在的文件 zj.dat ,再用CreateFileMap去映射,同样可以访问文件中的数据。
内存映射文件的机制是单纯的让访问文件变的简单。
    就好像文件流fstream模拟了输入输出流iostream一样,操作文件,就像操作cout,cin一样方便。
    同理,通过文件映射,操作文件就可以向操作内存一样方便。只是将这个机制用于进程间通信时,才需要考虑一端发送,一端接收,同步问题等。
共享内存中常存放结构体数组
    为了在各个进程当中共享数据,常常将自定义的结构体数组放到共享内存中(也就是说共享内存经常只存放一个变量,而这个变量是一个结构体数组)以此实现进程间数据的读写。本博客以字符串为例进行存储,将来有时间再修改程序。
共享内存中结构体中的字符串变量
由于共享内存当中需要直接开辟内存大小,存放结构体数组,每个结构体数组的内存大小是相同且固定的。因此结构体当中不能存放CString之类的不定长数据类型,否则在赋值的时候会报错(调试的时候可以发现,CString类型的变量此时所占内存大小为NULL)。可以用char来代替CString(如用char str[30]代替CSring str)。
---------------------

原文:https://blog.csdn.net/dashumak/article/details/83107889

MFC:通过代码简单理解进程间的通讯机制——共享内存相关推荐

  1. Linux进程间的通信----->共享内存

    共享内存:         顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物 ...

  2. linux进程间的通信(C): 共享内存

    一.共享内存介绍 共享内存是三个IPC(Inter-Process Communication)机制中的一个. 它允许两个不相关的进程访问同一个逻辑内存. 共享内存是在两个正在进行的进程之间传递数据的 ...

  3. python 进程间同步_python之路29 -- 多进程与进程同步(进程锁、信号量、事件)与进程间的通讯(队列和管道、生产者与消费者模型)与进程池...

    所谓异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了.至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠 ...

  4. 进程间的通讯(IPC)方式

    内存映射 为什么要进行进程间的通讯(IPC (Inter-process communication)) 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数 ...

  5. Nginx进程间的通信机制

    概述 linux进程间通讯方式 在linux系统中进程之间的通讯方式有套接字.共享内存.消息队列.管道.信号 Nginx进程间通讯方式 Nginx选择其中的套接字.共享内存.信号作为同步master进 ...

  6. 【Linux 应用编程】进程管理 - 进程间通信IPC之共享内存 mmap

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

  7. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  8. 进程的IPC操作 之 共享内存

    目录 一 共享内存的作用 二 共享内存的实现 2.1 shm系统调用 2.1.1 共享内存的创建 2.1.2 共享内存的关联与分离 2.1.3 共享内存的设置 2.1.4 测试案例 2.2 mmap内 ...

  9. IPC--进程间通信三(共享内存)

    1.什么是共享内存? 共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以 ...

最新文章

  1. 一文读懂卷积神经网络CNN(学习笔记)
  2. IPC 之 Binder 初识
  3. (转)解决在firefox下js调用as失败问题
  4. python中with as用法_python 中关于with...as的用法
  5. python用psf函数_python学习之-类的内置函数
  6. 求H21时的仿射变换要参考当前坐标系
  7. 作为开发者不应该畏惧的8件事
  8. unity中的透视投影矩阵
  9. A4双面打印多少钱一张
  10. 大数据在智慧城市建设中的应用
  11. (转)sonicstage 完整删除的方法
  12. ui设计需要学编程吗难不难学习
  13. lxml 爬取豆瓣top250
  14. WordPress 5.0的重要问题,答案已有
  15. 2017C语言程序设计预备作业
  16. 质量管理14条原则、敏捷开发宣言、敏捷开发十二原则
  17. 可以搜python题答案的app-python实现百万答题自动百度搜索答案
  18. java中获取指定时间的时间戳
  19. WPF MDI窗体的实现方法
  20. 健康贴示(尽力每日更新)2007-02-12

热门文章

  1. python学习-syspath、系统内置模块
  2. android studio复选按钮样式_Ubuntu与Android开发的邂逅
  3. python nonetype object has no_为什么会出现这个?'NoneType' object has no attribute 'contet
  4. python提高运行效率_提高 Python 运行效率的六个窍门
  5. 【STM32入门】这个项目绝了,用手势来产生波形,基于手势控制的波形发生器
  6. windows 11 预览版来了
  7. deepin编译Linux内核,为Deepin编译Linux 5.10内核的悲伤故事经历:从入门到卸载
  8. php zpo框架,Yii使用DeleteAll连表删除出现报错问题的解决方法
  9. BUUCTF--- LFI-------本地文件包含(Local File Include)
  10. python中如何调用函数_我写了一个函数,如何在python中调用