简述

共享内存(Shared Memory)是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。共享内存实际就是内存映射的一种特殊情况。在《windows核心编程》写道:

在Windows中,在同一台机器上数据共享的最底层机制就是内存映射文件。 这种数据共享机制是通过让两个或多个进程映射同一个文件映射对象的视图来实现,意味着在进程间共享相同的物理存储页面。对多个进程共享同一个文件映射对象来说,所有进程使用的文件映射对象的名称必须完全相同。

共享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,其它进程打开该文件映射对象就可以访问该内存块,这样每个进程都可以读取同一份数据,从而实现进程通信。因为是通过内存操作实现通信,因此是一种最高效的数据交换方法。由于共享内存是用文件映射实现的,所以它也有较好的安全性,也只能运行于同一计算机上的进程之间。

Qt提供了QSharedMemory类和QSystemSemaphore类,QSharedMemory可以访问共享内存区域,以及多线程和进程的共享内存区域。而QSystemSemaphore类用于访问系统共享资源,以实现独立进程间的通信。


效果


代码之路

共享端:

  1. 创建一个QSharedMemory,并设置一个key值
  2. 查看这个内存是不是被使用,如果被使用就断开
  3. 调用create进行创建
  4. 使用memcpy把要写入的数据放入QSharedMemory中(内部一般会使用互斥锁技术,锁住资源)

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QBuffer>
#include <QFileDialog>
#include <QDataStream>
#include <QSharedMemory>
#include <QPixmap>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;QSharedMemory *m_sharedMemory;
};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);//QSharedMemory类提供对共享内存段的访问,创建时设置key值,使用共享内存要有一个相同的key值m_sharedMemory = new QSharedMemory("1314");       //可以创建时设置key值,也可以用setKey()设置
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{//判断该进程是否已经附加到的共享内存段,如果是,就先分离if(m_sharedMemory->isAttached()) {if(!m_sharedMemory->detach()) {QMessageBox::information(this, tr("错误"), tr("共享内存失败"), QMessageBox::Yes);return;}}//选择要共享的文件QString fileName = QFileDialog::getOpenFileName(this,"","","Images(*.png *.jpg)");QImage image(fileName);ui->label->setPixmap(QPixmap::fromImage(image).scaled(330, 330));QBuffer buffer;buffer.open(QBuffer::ReadWrite);QDataStream out(&buffer);out << image;//创建共享内存段,失败则显示错误原因if(!m_sharedMemory->create(buffer.size())) {QMessageBox::information(this, tr("创建共享内存失败"), tr(m_sharedMemory->errorString().toLatin1().data()), QMessageBox::Yes);return;}m_sharedMemory->lock();          //把数据输入时锁定该共享内存段,其他进程将不能访问该共享内存char *to = (char*)m_sharedMemory->data();const char *from = buffer.data().data();memcpy(to, from, qMin(m_sharedMemory->size(), (int)buffer.size()));      //使用memcpy把要写入的数据拷贝入共享内存m_sharedMemory->unlock();        //输入完数据解锁共享内存
}

读取端:

  1. 创建一个QSharedMemory,把key值设置为分享端相同的key值
  2. 使用attach连接上这个QSharedMemory
  3. 以读取字节的方式读取QSharedMemory中的数据(内部一般会使用互斥锁技术,锁住资源)
  4. 使用detach端口对这个QSharedMemory的连接

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QBuffer>
#include <QDataStream>
#include <QPixmap>
#include <QSharedMemory>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;QSharedMemory *m_sharedMemory;
};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_sharedMemory = new QSharedMemory("1314");
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{//尝试将该进程附加到共享内存段,成功返回trueif(!m_sharedMemory->attach()){QMessageBox::information(this, tr("错误"), tr("共享内存失败"), QMessageBox::Yes);return;}//读取共享内存中的数据QBuffer buffer;QDataStream in(&buffer);QImage image;m_sharedMemory->lock();              //读取数据时锁定该共享内存段,其他进程将不能访问该共享内存buffer.setData((char *)m_sharedMemory->constData(),m_sharedMemory->size());buffer.open(QBuffer::ReadOnly);in>>image;//读取完解锁该共享内存段,并将该进程从共享内存段中分离出去m_sharedMemory->unlock();m_sharedMemory->detach();ui->label->setPixmap(QPixmap::fromImage(image));
}

源代码百度云下载地址:https://pan.baidu.com/s/1nsmxAB_JPdPIxJ9w7Kh9Iw     提取码:dl2e

QT 进程间通信——共享内存相关推荐

  1. QT实现共享内存进行进程间通信

    QT实现共享内存进行进程间通信 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 演示使用带有QSharedMemory类的共享内存进行进程间通信. 共享内存示例显示了 ...

  2. 操作系统实验报告7:进程间通信—共享内存。实现一个带有n个单元的线性表的并发维护。

    操作系统实验报告7 实验内容 实验内容:进程间通信-共享内存.实现一个带有n个单元的线性表的并发维护. 建立一个足够大的共享内存空间(lock, M),逻辑值lock用来保证同一时间只有一个进程进入M ...

  3. 操作系统实验报告6:进程间通信—共享内存

    操作系统实验报告6 实验内容 实验内容:进程间通信-共享内存. (1).验证:编译运行课件 Lecture 08 例程代码: Linux 系统调用示例 reader-writer 问题:Algorit ...

  4. C# 进程间通信(共享内存)

    原文:C# 进程间通信(共享内存) 进程间通信的方式有很多,常用的方式有: 1.共享内存(内存映射文件,共享内存DLL). 2.命名管道和匿名管道. 3.发送消息 本文是记录共享内存的方式进行进程间通 ...

  5. Linux基础入门--进程间通信--共享内存

    Linux基础入门--进程间通信--共享内存 1.共享内存IPC原理 2.共享内存管理 1.共享内存IPC原理 共享内存进程间通信机制主要用于实现进程间大量的数据传输,共享内存是在内存单独开辟的一段内 ...

  6. Linux下进程间通信--共享内存:最快的进程间通信方式

    内存共享最新整理: Linux下进程间通信-共享内存 - 码到城攻共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式https://www.codecomeon.com/posts/109/ ...

  7. 【Linux】Linux进程间通信——共享内存/消息队列/守护进程

    文章目录 进程间通信--共享内存/守护进程 一, 共享内存 1. 共享内存概念 2. 共享内存使用 1. 共享内存使用步骤 2. 共享内存操作函数 3. 共享内存常用操作命令 4. 共享内存使用示例: ...

  8. 【Linux系统编程】进程间通信--共享内存

    概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时 ...

  9. Linux系统【五】进程间通信-共享内存mmap

    mmap函数 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags,int fd, ...

最新文章

  1. 高薪程序员的5个工资档次
  2. 面试这么多人,发现越是没本事的人,自尊心越强
  3. 拥有全球最大指令集的“意念打字“系统,创下世界纪录
  4. 皮一皮:这个老爸有觉悟...
  5. Spark集群模式概述
  6. 如何为file增加文件类型的识别
  7. 标签在MPLS网络中的功能—Vecloud
  8. 这段 Python 代码让程序员赚 300W,公司已确认!网友:神操作!
  9. 电脑计算器_教训!19年中级败给了电脑计算器,CPA难道要步后尘?
  10. 恕我直言,你完全没有把IDEA的Diagram功能发挥出来...
  11. 售前更需要关注客户业务
  12. 苹果的文件传输服务器叫我们名字,苹果:即使是我们也无法对设备传输数据解密...
  13. 机器学习入门好文章--超级推荐
  14. 从几个实例来记忆Activity的生命周期
  15. 南大计算机专业课表,南京大学计算机科学与技术系2019-2020学年第一学期仙林校区.PDF...
  16. SceneBuilder中文版
  17. js实现查找删除功能
  18. 数字化住宅小区对计算机网络有需求,浅谈智能小区宽带接入及其技术发展趋势...
  19. python 方波信号_python实现周期方波信号频谱图
  20. 数据结构和算法学习之路-----必要的数学知识

热门文章

  1. 奇安信2023HVV面试笔记
  2. 图像中的目标检测学习笔记(一)
  3. 计算机视觉(二):局部图像描述子
  4. 烽火完成高性能、高集成度、更节能、易用性更好的Purley新平台服务器研发
  5. 如何快速学会php语言
  6. JavaScript百炼成仙阅读笔记
  7. mysql 5.7 多个_mysql5.7多实例
  8. webgl 2.0 测试_测试WebGL的极限:Babylon.js培训演示
  9. Java Web中动态网页开发基础重点总结
  10. 用 Python 自动生成 Word 文档