美文网首页
window 多进程通信:共享内存和事件

window 多进程通信:共享内存和事件

作者: 三木仔 | 来源:发表于2018-03-14 19:03 被阅读470次
进程通信

window 上跨进程通信主要有几种:共享内存、管道、事件、Socket、邮件槽等。

在了解学习了window的IPC机制,需要实现

  • 发送端与接收端跨进程通信;

  • 接收端可能处于正在运行或者未运行的状态,并且接收端可能上一次处于运行状态,这一次就可能终止运行了。

发送端:发送消息的一端,并且可能在接收端未启动时候,需要启动接收端;
接收端:负责接收信息的一端,随时可能关闭运行。


最后

  • 选择 共享内存机制 来传递消息的具体内容;

  • 结合使用 事件 机制 ,事件的一个方法 WaitForSingleObject 负责阻塞等待事件消息,既可以保证跨进程消息的即时性,同时也不需要用死循环来不断的查看共享内存是否有新的内容写入,减少了CPU的负载。

  • 如果不熟悉window共享内存,可以了解下: Windows 共享内存映射文件
    以及事件:Windows API 创建事件

发送端的流程:

#define BUF_SIZE 1025  
const char EventName [] = "EventName";
const char FileMapName [] = "MapFile";  

void Sender::start()
{
    std::cout<<"发送端"<<std::endl;
    fileMapHandler =  CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, MapFileName);
    charBuffer = (char *)MapViewOfFile( fileMapHandler, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);

    std::string input;
    while(1)
    {
        getline(std::cin, input);
        if (!input.empty())
        {
            strncpy(charBuffer, input.c_str(), BUF_SIZE - 1);
            charBuffer[BUF_SIZE - 1] = '\0';

            if (isReceiverWork())//判断接收端是否运行, 可以通过判断eventhandler是否存在或者接收端进程是否运行
            {
                eventHandler = OpenEvent(EVENT_ALL_ACCESS, FALSE,  EventName);//获取事件句柄
                SetEvent(eventHandler);//发送事件
            }
            else
            {
                startupReceiver();//启动接收端
            }
        }
    }
    //关闭
    UnmapViewOfFile(charBuffer);
    CloseHandle(fileMapHandler);
    CloseHandle(eventHandler);
}

接收端的流程:

void Receiver::start()
{
    std::cout<<"接收端"<<std::endl;
    while(1)
    {
        if (eventHandler != NULL)
        {
            ResetEvent(eventHandler);//重置为无信号状态
        }

        fileMapHandler = OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, LPCWCHAR(MapFileName));
        charBuffer = (char *)MapViewOfFile(fileMapHandler, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);  
        
        if (fileMapHandler != NULL)
        {
            if (charBuffer != NULL)
            {
                cout << "收到内容:"<<charBuffer << endl;
                memset(charBuffer, 0, strlen(charBuffer));
            }
        }
        if (eventHandler == NULL)
        {
            eventHandler = CreateEvent(NULL, FALSE, FALSE, LPCWSTR(EventName));
        }
        WaitForSingleObject(eventHandler, INFINITE);
    }
    //关闭
    UnmapViewOfFile(charBuffer);
    CloseHandle(fileMapHandler);
    CloseHandle(eventHandler);
}

以上

  1. 发送端负责创建共享内存句柄,接收端负责创建事件句柄。

  2. 发送端先写入共享内存,启动客户端后会默认先读取共享内存,再进入事件等待;这样能解决:在发送端首次想告诉客户端消息,可是客户端还未启动、发送端也还没拿到事件句柄的时候,在接收端第一次启动之后,接收端马上拿取共享内存的内容,实现了第一次的消息通信,以后后续的消息通过事件告知接收端,接收端再从共享内存打开获取具体消息内容。

  3. 每次发送端都重新获取一次句柄是因为接收端可能随时断开,生成新的一次句柄,解决了接收端状态不稳定的问题。

一点想法

个人对window IPC机制不熟悉,不过相信可能有更好的处理方式,例如邮件槽,边学习边努力吧。

相关文章

  • window 多进程通信:共享内存和事件

    window 上跨进程通信主要有几种:共享内存、管道、事件、Socket、邮件槽等。 在了解学习了window的I...

  • Android

    ContentProvider 作用 进程间数据共享 即跨进程通信 原理 Binder进程间通信结合匿名共享内存(...

  • 共享内存

    Linux进程间通信 - 共享内存

  • Java并行

    并行的2个模型 共享内存 消息通信 进程和线程的区别 进程拥有私有的内存区域(现代处理器可以使得进程有共享的内存区...

  • 进程通信:共享内存,套接字

    进程通信方式:共享内存 共享内存本质上就是每个进程将虚拟地址空间指向共享内存块中,当一个进程往一个共享内存快中写入...

  • Android学习--binder机制(一)原理

    前言 binder是Android的一套进程间通信框架,用来跨进程发送消息,同步和共享内存。 1.进程间通信 进程...

  • 零散的小知识记录(待补充和修改)

    Android跨进程通信:Binder,socket/管道/消息队列,共享内存; linux进程间通信:管道,Bi...

  • Binder IPC 通信学习笔记

    一、Android 中IPC 跨进程通信方式 1.1、Linux下的进程通信: 进程间隔离进程与进程间内存是不共享...

  • 2018-08-06

    【转】父子进程通信的两种方式--消息队列和共享内存 man mmap

  • Linux共享内存

    共享内存是常用的进程之间的通信,两个进程可以直接共享访问同一块内存区域 一、共享内存的实现步骤如下: (1)创建共...

网友评论

      本文标题:window 多进程通信:共享内存和事件

      本文链接:https://www.haomeiwen.com/subject/fcooxftx.html