Windows进程通信(IPC)之共享内存

摘要:
在windows编程中,有个概念是句柄,句柄指向资源,其中文件操作,可以将文件映射到内存,此处的文件是广义的文件,可以指内存对象,邮件槽等。在windows中创建一个指向文件的虚拟内存,然后多个进程创建各个进程对这块内存的映射,通过访问各个进程的映射内存对这块虚拟内存进行访问,是共享内存实现的原理。

前言:我们知道windows os上有很多的api,编程语言对os进行操作,无论什么语言,最终都是通过windows api 的。

在windows编程中,有个概念是句柄,句柄指向资源(一切可以利用的物理的逻辑的资源),其中文件操作,可以将文件映射到内存,此处的文件是广义的文件,可以指内存对象,邮件槽等。

在windows中创建一个指向文件的虚拟内存,然后多个进程创建各个进程对这块内存的映射,通过访问各个进程的映射内存对这块虚拟内存进行访问,是共享内存实现的原理。

下图很好的标明了整个原理。

Windows进程通信(IPC)之共享内存第1张

一、相关的API函数

内存映射API函数CreateFileMapping创建一个有名的共享内存:

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

HANDLE CreateFileMapping(
HANDLE hFile, //物理文件句柄
LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
DWORD flProtect, //保护设置
DWORD dwMaximumSizeHigh, //高位文件大小
DWORD dwMaximumSizeLow, //低位文件大小
LPCTSTR lpName //共享内存名称
);
hFile 指定欲在其中创建映射的一个文件句柄。INVALID_HANDLE_VALUE,即0xFFFFFFFF表示在页面文件中创建一个可共享映射文件。
lpAttributes 它指明返回的句柄是否可以被子进程所继承,指定一个安全对象,在创建文件映射时使用。如果为NULL(用ByVal As Long传递零),表示使用默认安全对象
flProtect 有以下几种方式:
PAGE_READONLY 以只读方式打开映射
PAGE_READWRITE 以可读、可写方式打开映射
PAGE_WRITECOPY 为写操作留下备份也可组合使用下述一个或多个常数:
SEC_COMMIT 为文件映射一个小节中的所有页分配内存
SEC_IMAGE 文件是个可执行文件
SEC_RESERVE 为没有分配实际内存的一个小节保留虚拟内存空间
dwMaximumSizeHigh 文件映射的最大长度的高32位
dwMaximumSizeLow 文件映射的最大长度的低32位。如这个参数和dwMaximumSizeHigh都是零,就用磁盘文件的实际长度。
lpName 指定文件映射对象的名字。如存在这个名字的一个映射,函数就会打开它。用vbNullString可以创建一个无名的文件映射。

LPVOID WINAPI MapViewOfFile( //将一个文件映射对象映射到当前应用程序的地址空间。
__in HANDLE hFileMappingObject,
__in DWORD dwDesiredAccess,
__in DWORD dwFileOffsetHigh,
__in DWORD dwFileOffsetLow,
__in SIZE_T dwNumberOfBytesToMap
);
hFileMappingObject 为CreateFileMapping返回的文件映像对象句柄。
dwDesiredAccess 映射对象的文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配。
可取以下值:
FILE_MAP_ALL_ACCESS 等价于CreateFileMapping的 FILE_MAP_WRITE|FILE_MAP_READ.文件映射对象被创建时必须指定PAGE_READWRITE 选项.
FILE_MAP_COPY 可以读取和写入文件.写入操作会导致系统为该页面创建一份副本.在调用 CreateFileMapping时 必须 传入PAGE_WRITECOPY保护属性.
FILE_MAP_EXECUTE 可以将文件中的数据在调用CreateFileMapping时可以传入PAGE_EXECUTE_READWRITE或PAGE_EXECUTE_READ保护属性.
FILE_MAP_READ 可以读取文件.在调用CreateFileMapping时可以传入PAGE_READONLY或PAGE_READWRITE保护属性.
FILE_MAP_WRITE 可以读取和写入文件.在调用CreateFileMapping时必须传入PAGE_READWRITE保护属性.
dwFileOffsetHigh 表示文件映射起始偏移的高32位.
dwFileOffsetLow 表示文件映射起始偏移的低32位.(64KB对齐不是必须的)
dwNumberOfBytes 指定映射文件的字节数.

三、写端的实现

#include <iostream>#include <windows.h>#include <string.h>#include <cstring>#include <istream>
using namespacestd;

intmain()
{
    unsigned long buff_size = 1024 * 5;

    PVOID pBuff=NULL;

    HANDLE hFile = CreateFile(L"shared_memory",    //如果不映射到物理磁盘上,可以不用创建
        GENERIC_READ |GENERIC_WRITE,
        FILE_SHARE_READ |FILE_SHARE_WRITE,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hFile==INVALID_HANDLE_VALUE)
    {
        cout << "create file error." <<endl;
    }

    HANDLE hFile_mapping =CreateFileMapping(
        INVALID_HANDLE_VALUE,                  //如果需要创建,而不是内存对象,可以传入hFile
NULL,
        PAGE_READWRITE,
        0,
        buff_size,
        L"shared_memory");

    if (NULL !=hFile_mapping)
    pBuff =MapViewOfFile(
        hFile_mapping,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        buff_size
    );

    char str[1024];

    while (true)
    {
        cout << "please enter data ."exit" end app" <<endl;
        cin.getline(str,1024);
        if (str!="exit")
        {
            if (NULL !=pBuff)
                memcpy(pBuff, str, 1024);
        }
        else if (str == "exit")
        {
            break;
        }

    }

    if (NULL !=pBuff)
        FlushViewOfFile(pBuff, buff_size);

    cout << "finish write, wait ..." <<endl;
    Sleep(20000);

    if (NULL!=pBuff)
        UnmapViewOfFile(pBuff);

    if (NULL !=hFile_mapping)
        CloseHandle(hFile_mapping);

    if (NULL !=hFile)
        CloseHandle(hFile);

}

四、读端的实现

#include <iostream>#include <windows.h>
using namespacestd;

intmain()
{
    const unsigned long buff_size = 1024*5;
    LPVOID pBuff =NULL;

    HANDLE handle_file_mapping =OpenFileMapping(
        FILE_MAP_ALL_ACCESS,
        NULL,
        L"shared_memory");

    if (NULL!=handle_file_mapping)
        pBuff =MapViewOfFile(
            handle_file_mapping,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        0);

    if (handle_file_mapping==NULL|| pBuff==NULL)
    {
        cout << "create shared memory faild,please waitting the memory created and exect the app again!" <<endl
             <<"enter any key to  exit the app!";
        stringtemp;
        cin >>temp;
        return 0;
    }

    stringstr;

    while (true)
    {
        cout << "enter "yes" receive data, or enter "exit" " <<endl;
        cin >>str;
        if (str=="yes")
        {
            char* share_buffer = (char*)pBuff;
            cout << share_buffer <<endl;
        }
        else if (str == "exit")
        {
            break;
        }

    }

    if (NULL!=pBuff)
        UnmapViewOfFile(pBuff);
    if (NULL !=handle_file_mapping)
        CloseHandle(handle_file_mapping);
    return 0;
}

五、结果如下

Windows进程通信(IPC)之共享内存第2张

免责声明:文章转载自《Windows进程通信(IPC)之共享内存》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Simulink仿真入门到精通(十) S函数十三、ES备份恢复下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Socket异步通信——使用SocketAsyncEventArgs

  上一次的博文说错了东西,幸好有园友指出。才把错误改正过来,顺便也把利用SocketAsyncEventArgs进行Socket异步通信这方面的知识整理一下。       之前看了网上的代码,每进行一次异步操作都new 一个SocketAsyncEventArgs对象,然后网友评论太浪费资源了,于是就误以为用BeginXXX进行Socket异步通信会更优...

我的WCF之旅 (11): 再谈WCF的双向通讯基于Http的双向通讯 V.S. 基于TCP的双向通讯

在一个基于面向服务的分布式环境中,借助一个标准的、平台无关的Communication Infrastructure,各个Service通过SOAP Message实现相互之间的交互。这个交互的过程实际上就是Message Exchange的过程。WCF支持不同形式的Message Exchange,我们把这称之为Message Exchange Patt...

计算机邮件TCp / Ip 简介

最近用使开发的过程中出现了一个小问题,顺便记录一下原因和方法--计算机邮件     1. TCP/IP 是用于因特网 (Internet) 的通信议协。            计算机通信议协是对那些计算机必须守遵以便彼此通信的的规矩的描述。     TCP/IP 指传输控制议协/网际议协 (Transmission Control Protocol / I...

c/s架构nginx+php-fpm通信原理

    FastCGI是一个运用于Http Server和动态脚本语言间通信的接口,多数流行的Http Server都支持FastCGI,包括Apache、Nginx和lighttpd等。同时,FastCGI也被许多脚本语言支持,其中就有PHP。    FastCGI接口方式采用C/S结构,可以将HttP服务器和脚本解析服务器分开,同时在脚本解析服务器上...

专业术语常用名词缩写中英文对照

A:Actuator 执行器A:Amplifier 放大器A:Attendance员工考勤A:Attenuation衰减AA:Antenna amplifier 开线放大器AA:Architectural Acoustics建筑声学AC:Analogue Controller 模拟控制器ACD:Automatic Call Distribution 自动...

VC 串口通讯基本原理,讲的很是详细

目 录打开串口........................................................................................................................ 2关闭串口.................................................