【C/C++实现进程间通信 一】共享内存方式

news2024/9/22 7:33:30

前情回顾:

上一期已经讲解过了进程的相关概念以及进程间通信的实现原理,下面仅展示相关代码。

思路:

/* 本项目主要用于对同主机上以共享内存方式进行进程间通信的测试 。
1.包含一个外部程序 publisherDemo.exe 以及 subscriberDemo.exe。
2.publisherDemo 主要功能是实现定时信息发布,并将信息发送到共享内存。
3.subscriberDemo 主要功能是实现访问指定共享内存,对publisherDemo.exe进程发布的信息进行捕获。
4.此外,本项目还利用信号量机制实现了进程间的同步发送与接收的功能。
*/

源码:

环境:Windows 64位 + QtCreator

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

效果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/697708.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Selenium 使用已开启的浏览器执行测试

实际测试工作中可能遇到某些需要使用手动开启浏览器执行测试的情况&#xff0c;比如某些网站登录需要手机短信验证&#xff0c;为了跳过这步&#xff0c;可以手动登录网站&#xff0c;在已登录的页面继续测试 1、找到本地安装的浏览器启动路径&#xff0c;例如Chrome C:\Progra…

无锡斑目信息技术有限公司与无锡漫途科技有限公司签署战略伙伴合作协议!

2023年6月21日无锡斑目信息技术有限公司与无锡漫途科技有限公司签署战略伙伴合作协议。双方将在数字工厂、智慧城市等领域凭借各自的优势进行全方面的合作。 漫途传感科技总经理田吉成、无锡艾森汇智科技总经理钱小伟、无锡数字城市建设发展工业互联网事业部部长王威共同参加签…

注解实现防止重复提交(Aop)

一、前言 书接上回&#xff0c;上次实现了springboot整合redis&#xff0c;在使用过程中就避免不了重复提交的场景。springboot整合redis_crazyK.的博客-CSDN博客 重复提交的场景&#xff1a; 用于用户误操作&#xff0c;多次点击表单提交按钮由于网速等原因造成页面卡顿&am…

软考高级架构师笔记-8软件工程

目录 1. 前言 & 考情分析2. 软件工程概述3. 能力成熟度模型4. 软件过程模型4.1 敏捷模型4.2 统一过程模型(RUP)5. 逆向工程6. 需求工程7. 系统设计8. 测试基础知识9. 系统运行与维护10. 净室软件工程11. 结语1. 前言 & 考情分析 前文回顾: 软考高级架构师笔记-1计算机…

C++—指针与引用的区别与联系

一、为什么要有引用&#xff08;C语言没有&#xff09; ▪ 因为引⽤和值有⼀样的语义&#xff0c;而指针不是 ▪ 不存在空引⽤&#xff0c;必须初始化&#xff1b;保证值不变&#xff0c;保证编译器更加安全 ▪ 加减号、赋值操作符&#xff0c;作⽤在引用上会触发对象的操作符重…

PHP 人才信息与招聘系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 人才信息与招聘系统 是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为PHP APACHE&#xff0c;数据 库为mysql5.0&#xff0c;使用php语言开发。…

Qt笔记-自定义QSet,QHash的Key

官方文档已经说得很详细了。 If you want to use other types as the key, make sure that you provide operator() and a qHash() implementation. Example:#ifndef EMPLOYEE_H#define EMPLOYEE_Hclass Employee{public:Employee() {}Employee(const QString &name, con…

在 Linux 中配置 IPv4 和 IPv6 地址详解

概要 IPv4和IPv6是Internet上常用的两种IP地址协议。在Linux系统中&#xff0c;您可以通过配置网络接口来设置IPv4和IPv6地址。本文将详细介绍如何在Linux中配置IPv4和IPv6地址。 步骤 1&#xff1a;确定网络接口 在开始配置IP地址之前&#xff0c;您需要确定要配置的网络接口…

CSDN竞赛第59期-参赛体验

CSDN竞赛第59期-参赛体验 前言介绍 体验收获反馈准备认可最后 前言 博主空空star主页空空star的主页 大家好&#xff0c;我是空空star&#xff0c;本篇给大家分享一下《CSDN竞赛第59期-参赛体验》。 介绍 CSDN竞赛 体验 我报名参加了CSDN举办的一场编程比赛&#xff0c;这是…

MacOS 升级golang版本后无法debug,升级delve版本

golang版本升级到1.20以后导致debug失效了&#xff0c;本文针对MacOS系统&#xff0c;win系统也可作参考。 WARNING: undefined behavior - version of Delve is too old for Go version 1.20.4 (maximum supported version 1.19) 1、升级delve版本 brew install delve 安装…

重命名Github的默认分支名

- 最简单的办法是在github网站直接重命名&#xff0c;但是比较危险&#xff0c;因为有很多其他人已经把这个分支拉到本地了 - 另一个办法是基于当前的主分支&#xff0c;新建一个你要重命名的目标名字的分支 - git checkout 当前主分支名 - git checkout -b 目标主分支名 - git…

CentOS 挂载ntfs格式U盘

1、查看磁盘信息 fdisk -l 如上图所示&#xff0c;可以看到插入的U盘/dev/sdc 2、查看磁盘块信息 lsblk 如上图所示&#xff0c;sdc即是插入的U盘&#xff0c;sdc1为磁盘块&#xff0c;挂载的时候使用sdc1 3、查看磁盘文件系统类型 parted -l 如上图所示&#xff0c;U盘是WD…

分布式、服务化的ERP系统架构设计

ERP之痛 曾几何时&#xff0c;我混迹于电商、珠宝行业4年多&#xff0c;为这两个行业开发过两套大型业务系统&#xff08;ERP&#xff09;。作为一个ERP系统&#xff0c;系统主要功能模块无非是订单管理、商品管理、生产采购、仓库管理、物流管理、财务管理等等。作为一个管理系…

【数据结构】单链表(超全)

目录 一、什么是链表&#xff1f;1.1 定义1.2 链表的分类 二、无头单向非循环链表2.1 结构2.2 如何遍历链表数据2.3 尾插2.4 创建新节点2.5 头插2.6 尾删2.7 头删2.8 单链表查找2.9 在pos位置之前插入2.10 删除pos位置数据2.11 在pos位置的后面插入2.12 删除pos位置后面的数据 …

Markdown学习

我展示的是一级标题 我展示的是二级标题 斜体文本 斜体文本 粗体文本 粗体文本 粗斜体文本 粗斜体文本 第一项第二项第三项 第一项第二项第三项 第一项第二项第三项 第一项&#xff1a; 第一项嵌套的第一个元素第一项嵌套的第二个元素 第二项&#xff1a; 第二项嵌套的第…

mysql 常见锁类型

表锁 & 行锁 在 MySQL 中锁的种类有很多&#xff0c;但是最基本的还是表锁和行锁&#xff1a;表锁指的是对一整张表加锁&#xff0c;一般是 DDL 处理时使用&#xff0c;也可以自己在 SQL 中指定&#xff1b;而行锁指的是锁定某一行数据或某几行&#xff0c;或行和行之间的…

ROS2 lifecycle node生命周期节点 官方例程文档翻译

0 官方例程文档 ros2 humble lifecycle demo github repo 1 引言 ROS2引入了受管理节点的概念&#xff0c;受管理的节点又被称为是生命周期节点&#xff08;LifecycleNode&#xff09;。在接下来的教程中&#xff0c;我们会解释这些节点的作用&#xff0c;是什么使得它们和普…

【Linux 驱动篇(三)】新字符设备驱动

文章目录 一、新字符设备驱动原理1. 分配和释放设备号2. 新的字符设备注册方法2.1 字符设备结构2.2 cdev_init 函数2.3 cdev_add 函数2.4 cdev_del 函数 二、自动创建设备节点1. mdev 机制2. 创建和删除类3. 创建设备4. 参考示例5. 设置文件私有数据 三、LED 灯驱动程序编写四、…

Q-Learning 原理干货讲解

强化学习 本文是强化学习和Q-Learning算法的概念及原理 项目实战案例可查看下一篇文章&#xff1a;Q-Learning 单路径吃宝箱问题–棋盘格吃宝箱问题–拓扑节点较优路径问题 一. 强化学习概述 1.1 什么是强化学习 基于环境的反馈而行动&#xff0c;通过不断与环境的交互、试错&…

AR急诊急救大平台远程专家会诊方案

随着AR技术的完善&#xff0c;在医院急救中&#xff0c;需要及时把各方面专家汇在一起会诊&#xff0c;在AR这方面有数据采集清晰&#xff0c;资料呈现方便便捷&#xff0c;针对客户需要&#xff0c;我们对业务需求分析&#xff0c;比较市面多种产品&#xff0c;把会议&#xf…