【C/C++によるプロセス間通信の実装1】共有メモリ方式

前回の状況レビュー

前回はプロセスの概念とプロセス間通信の実装原理について説明しましたが、ここではプロセス間通信を共有メモリで実装するためのコードのみを示します。

一連の考え

/* このプロジェクトは主に、同じホスト上の共有メモリを使用したプロセス間通信をテストするために使用されます。
1. 外部プログラムのpublisherDemo.exeとsubscriberDemo.exeが含まれています。
2. PublisherDemo の主な機能は、タイミング情報のパブリッシングを実装し、その情報を共有メモリに送信することです。
3.subscriberDemo の主な機能は、指定された共有メモリにアクセスし、publisherDemo.exe プロセスによって公開された情報を取得することです。
4. また、本プロジェクトではセマフォ機構を利用してプロセス間の同期送受信機能も実現しています。
*/

ソースコード

環境: Windows 64 ビット + QtCreator
には WINAPI の一部の機能が含まれます。具体的な機能の分析については、公式 WINAPI ドキュメントを参照してください。

パブリッシャー.cpp

#include <QCoreApplication>
#include <Windows.h>
#include <iostream>
using namespace std;

#define BUF_SIZE 4096

HANDLE g_EventRead;		// 读信号灯
HANDLE g_EventWrite;	// 写信号灯
// 定义共享数据
char szBuffer[] = "Hello, shared memory!";
/* 读取con1串口的线程 */
DWORD __stdcall WriteThread(const LPVOID lp)
{
    
    
    while (true)
    {
    
    
        WaitForSingleObject(g_EventWrite, INFINITE); // 等待读数据的信号

        // 将数据拷贝到共享内存
        strcpy((char*)lp, szBuffer);
        cout << "数据发送成功!等待订阅端接受:" << (char*)lp << endl;

        Sleep(1000);

        SetEvent(g_EventRead);
        ResetEvent(g_EventWrite);
    }
    return DWORD();
}


int main(int argc, char *argv[])
{
    
    
    QCoreApplication a(argc, argv);

    // 创建共享文件句柄
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,               // 物理文件句柄  NVALID_HANDLE_VALUE  则创建一个进程间共享的对象
        NULL,                               // 默认安全级别
        PAGE_READWRITE,                     // 可读可写
        0,                                  // 高位文件大小
        BUF_SIZE,                           // 低位文件大小
        L"ShareMemoryPDU"                   // 映射文件名,即共享内存的名称
    );

    if (0 == hMapFile)
    {
    
    
        return 0;
    }

    // 映射缓存区视图 , 得到指向共享内存的指针
    // 将hFileMapping共享内存衍射到本进程的地址空间中
    LPVOID lpBase = MapViewOfFile(
        hMapFile,                           // 共享内存的句柄
        FILE_MAP_ALL_ACCESS,                // 可读写许可
        0,
        0,
        BUF_SIZE
    );

    if (0 == lpBase)
    {
    
    
        return 0;
    }

    g_EventRead = CreateEventW(NULL, TRUE, FALSE, TEXT("EventRead"));
    if (nullptr == g_EventRead)
    {
    
    
        return 0;
    }

    g_EventWrite = CreateEventW(NULL, TRUE, TRUE, TEXT("EventWrite"));
    if (nullptr == g_EventRead)
    {
    
    
        return 0;
    }

    HANDLE handle = CreateThread(NULL, 0, WriteThread, lpBase, 0, NULL);

    WaitForSingleObject(handle, INFINITE);

    // 解除文件映射
    UnmapViewOfFile(lpBase);

    // 关闭内存映射文件对象句柄
    CloseHandle(hMapFile);
    return 0;
    return a.exec();
}

購読者.cpp

#include <QCoreApplication>
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;

#define BUF_SIZE 4096

HANDLE g_EventRead;		// 读信号灯
HANDLE g_EventWrite;	// 写信号灯


DWORD __stdcall ReadThread(const LPVOID lp)
{
    
    
    while (true)
    {
    
    
        WaitForSingleObject(g_EventRead, INFINITE); // 等待读数据的信号
    	// 将共享内存数据拷贝出来
        char szBuffer[BUF_SIZE]{
    
     0 };

        strcpy_s(szBuffer, (char*)lp);

        std::cout << "订阅端读取数据成功!:" << szBuffer << endl;

        ResetEvent(g_EventRead); /* 将读取信号关闭  */
        SetEvent(g_EventWrite);
    }
}


int main(int argc, char *argv[])
{
    
    
    QCoreApplication a(argc, argv);
    // 打开共享的文件对象
    HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, L"ShareMemoryPDU");

    if (0 == hMapFile)
    {
    
    
        // 打开共享内存句柄失败
        std::cout << "打开共享内存失败!" << endl;
        return 0;
    }
    LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (0 == lpBase)
    {
    
    
        return 0;
    }

    g_EventRead = CreateEventW(NULL, TRUE, FALSE, TEXT("EventRead"));
    if (nullptr == g_EventRead)
    {
    
    
        return 0;
    }

    g_EventWrite = CreateEventW(NULL, TRUE, TRUE, TEXT("EventWrite"));
    if (nullptr == g_EventRead)
    {
    
    
        return 0;
    }

    HANDLE handle = CreateThread(NULL, 0, ReadThread, lpBase, 0, NULL);
    if (0 == handle)
    {
    
    
        return 0;
    }

    WaitForSingleObject(handle, INFINITE);
    // 解除文件映射

    UnmapViewOfFile(lpBase);
    // 关闭内存映射文件对象句柄
    CloseHandle(hMapFile);

    return a.exec();
}

注: 上記のプログラムの実行順序は、最初に Subscriber.exe を起動し、次に Publisher.exe を起動する必要があります。

効果

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/wddkxg/article/details/131427612