[C/C++ implements inter-process communication 1] Shared memory method

Previous situation review

The previous issue has explained the concept of process and the implementation principle of inter-process communication. The following only shows the relevant code for implementing inter-process communication in the way of shared memory.

train of thought

/* This project is mainly used to test the inter-process communication in the way of shared memory on the same host.
1. Contains an external program publisherDemo.exe and subscriberDemo.exe.
2. The main function of publisherDemo is to implement timing information publishing and send the information to the shared memory.
3. The main function of subscriberDemo is to access the specified shared memory and capture the information published by the publisherDemo.exe process.
4. In addition, this project also uses the semaphore mechanism to realize the function of synchronous sending and receiving between processes.
*/

source code

Environment: Windows 64-bit + QtCreator
involves some functions in WINAPI. For specific function analysis, please refer to the official WINAPI document

Publisher.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();
}

Subscriber.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();
}

Note: The running sequence of the above programs should be: start Subscriber.exe first, and then start Publisher.exe.

Effect

insert image description here

Guess you like

Origin blog.csdn.net/wddkxg/article/details/131427612