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

进程通信

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机制不熟悉,不过相信可能有更好的处理方式,例如邮件槽,边学习边努力吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容