简述

上一节中,我们分享下如何利用Windows消息机制来进行不同进程间的通信。但是有很多局限性,比如:不能跨平台,而且必须两个进程同时存在才可以,要么进程A发了消息谁接收呢?

下面我们来分享另外一种跨平台的进行间通信的方式-Shared Memory(共享内存)。

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

QSharedMemory

QSharedMemory读写内存时,可以使用lock()实现同步。因此,如果同步完成,必须使用unlock()为共享内存区域解锁。

QSharedMemory可以使用attach()访问共享内存。可以通过指定参数来设置共享内存的访问模式。如果使用的是QSharedMemory::ReadOnly模式,则只能通过只读模式访问共享内存。反之,使用QSharedMemory::ReadWrite模式则可以通过读写模式访问共享内存。

QSharedMemory拥有进程并提供可以返回共享内存区域指针的成员函数。在共享内存区域,成员函数constData()可以通过void类型返回进程正在使用的内存区域指针。创建共享时,QSharedMemory可以以字节为单位分配共享内存区域,还可以通过第二个参数设置函数attach()提供的模式。

QSharedMemory可以设置特定共享内存的固定键。函数setNativeKey()可以设置共享内存对象的键,该函数使用从属平台的共享内存的键进行相关设置。相反,使用函数setKey()可以设置与独立与平台的键。函数setKey()创建与平台本地键(Native Key)映射的键。

QSystemSemaphore

QSystemSemaphore可以提供普通系统的信号量。信号量使用互斥体,而互斥体只可以使用1次锁定(Block)。因此,QSemaphore类不能对有效资源使用多线程,而QSystemSemaphore类可以再多进程或多线程中实现。

QSystemSemaphore与QSemaphore类不同,可以访问多进程。这表示QSystemSemaphore是一个重量级的类。因此,使用单一线程或进程时,建议使用QSemaphore。获得资源前,成员函数acquire()始终阻塞。函数release()用于释放资源,且该函数可以设置参数。该函数的参数>1时,释放资源。

注意事项

初始化QSharedMemory时,必须指定一个唯一的标识Key,进程的Key必须保持一致。可以使用setKey来设置。

加载进内存

说明

进程A-写

分为下面几步:

  1. 检测该进程是否连接到共享内存段,如果连接,则将该进程与共享内存段分离。
  2. 从系统足够大的内存中得到一个新的共享内存段。
  3. 锁定该共享内存段,以阻止第二个对话框进程访问,将缓冲区中的图片复制进共享内存段。
  4. 将共享内存段解锁,然后第二个对话框进程就可以访问了。

实现

void Dialog::loadFromFile()
{
if (sharedMemory.isAttached())
{
// 将该进程与共享内存段分离
if (!sharedMemory.detach())
qDebug() << "Unable to detach from shared memory.";
} QString fileName = QFileDialog::getOpenFileName(0, QString(), QString(),
tr("Images (*.png *.xpm *.jpg)"));
QImage image;
if (!image.load(fileName))
{
qDebug() << "Selected file is not an image, please select another.";
return;
} // 将数据加载到共享内存中
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
out << image;
int size = buffer.size(); // 创建共享内存段
if (!sharedMemory.create(size))
{
qDebug() << sharedMemory.errorString() << "\n Unable to create shared memory segment.";
return;
}
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();
}

从内存中读取

说明

进程B-读

分为下面几步:

  1. 将该进程与进程A创建的共享内存段绑定
  2. 锁定共享内存段,复制数据到缓冲区,然后写入到QImage中。
  3. 将共享内存段解锁,然后将该进程与共享内存段分离。

实现

void MainWindow::loadFromMemory()
{
// 将共享内存与该进程绑定
if (!sharedMemory.attach())
{
qDebug() << "Unable to attach to shared memory segment.";
return;
} // 从共享内存中读取数据
QBuffer buffer;
QDataStream in(&buffer);
QImage image; sharedMemory.lock();
buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
buffer.open(QBuffer::ReadOnly);
in >> image;
sharedMemory.unlock(); sharedMemory.detach();
m_pLabel->setPixmap(QPixmap::fromImage(image));
}

Qt之进程间通信(共享内存)的更多相关文章

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

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

  2. Linux环境进程间通信: 共享内存

    Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...

  3. linux进程间通信-共享内存

    转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...

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

    共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...

  5. Linux进程间通信—共享内存

    五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...

  6. Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收

    之前以为两个互不相关的程序a.exe b.exe通信就只能通过网络,人家说可以通过发消息,我还深以为不然,对此,我表示万分惭愧. 之前课本上说的进程间通信,有共享内存.管道等之类的,但没有自己操刀写过 ...

  7. Linux 进程间通信 共享内存

    1.特点: 1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝.如管道当在内核空间创建以后,用户空间需要内存  拷贝,需要拷贝数据,所以效率低. 2)为了在多个进 ...

  8. linux 进程间通信 共享内存 shmat

    系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件(这是通过shm ...

  9. linux 进程间通信 共享内存 mmap

    共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反 ...

  10. win32下进程间通信——共享内存

    一.引言     在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...

随机推荐

  1. Maven实站读后感

    这本书是一本非常经典的Maven教程,通俗易懂,同时介绍的东西十分实用,在工作上都能用到. 以前在公司里面需要要问同时的有关的Maven的问题,都可以自己解决了. 除了最基本的,以后自己可能要用到的: ...

  2. android动态增加控件时控制样式的方法

    在学习android的动画时,发现所谓的tween动画只是改变绘制效果并不改变原控件的位置时是颇为失望的,虽然3.0之后已经有了property animation,但是由于要兼容老版本的androi ...

  3. ADT eclipse打开时出现Error: Error parsing C:\Users\admin*\.android\devices.xml

    Error: Error parsing C:\Users\admin*\.android\devices.xml  在ADT eclipse打开项目的时候出现此提示,但是又不影响使用. 原因:之前安 ...

  4. IOS crash分析

    此处不讨论具体的如何根据.dsym文件解析crash log的方式. 什么是崩溃: 不希望出现的中断,APP收到了系统发出的unhandle signal,来源主要由系统内核,处理器,或者应用程序本身 ...

  5. [转载]如何申请淘宝app_key、app_secret、SessionKey?

    不知道如何申请淘宝开发平台的App Key?其实申请App key很简单,主要了解申请步骤以及各个App key的数据阶段状态就可以了!下面由淘客帝国为您做详细图文讲解!申请比较简单,不过为了新手能够 ...

  6. web系统之session劫持解决

    session劫持是一种比较复杂的攻击方法.大部分互联网上的电脑多存在被攻击的危险.这是一种劫持tcp协议的方法,所以几乎所有的局域网,都存在被劫持 可能. 两台主机要想进行TCP通信,必须经过一个三 ...

  7. iOS 通过代码关闭应用程序

    //-------------------------------- 退出程序 -----------------------------------------// - (void)exitAppl ...

  8. jstl if条件判断字符串代码

    <c:if test="${netWorkInfo.networkType eq '快修店'}"> <input type="radio" n ...

  9. java poi导出EXCEL xls文件代码

    String _currentPage = request.getParameter("currentPage"); Integer currentPage = 0; if(_cu ...

  10. linux源码阅读笔记 fork函数

    在阅读源码的过程中,发现找不到fork函数的定义.后来在linux/init/main.c中找到了这样一条语句 static inline _syscall0(int,fork) 原来这里就是fork ...