Qt之进程间通信(共享内存)
简述
上一节中,我们分享下如何利用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-写
分为下面几步:
- 检测该进程是否连接到共享内存段,如果连接,则将该进程与共享内存段分离。
- 从系统足够大的内存中得到一个新的共享内存段。
- 锁定该共享内存段,以阻止第二个对话框进程访问,将缓冲区中的图片复制进共享内存段。
- 将共享内存段解锁,然后第二个对话框进程就可以访问了。
实现
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-读
分为下面几步:
- 将该进程与进程A创建的共享内存段绑定
- 锁定共享内存段,复制数据到缓冲区,然后写入到QImage中。
- 将共享内存段解锁,然后将该进程与共享内存段分离。
实现
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之进程间通信(共享内存)的更多相关文章
- C# 进程间通信(共享内存)
原文:C# 进程间通信(共享内存) 进程间通信的方式有很多,常用的方式有: 1.共享内存(内存映射文件,共享内存DLL). 2.命名管道和匿名管道. 3.发送消息 本文是记录共享内存的方式进行进程间通 ...
- Linux环境进程间通信: 共享内存
Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...
- linux进程间通信-共享内存
转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...
- Linux下进程间通信--共享内存:最快的进程间通信方式
共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...
- Linux进程间通信—共享内存
五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...
- Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收
之前以为两个互不相关的程序a.exe b.exe通信就只能通过网络,人家说可以通过发消息,我还深以为不然,对此,我表示万分惭愧. 之前课本上说的进程间通信,有共享内存.管道等之类的,但没有自己操刀写过 ...
- Linux 进程间通信 共享内存
1.特点: 1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝.如管道当在内核空间创建以后,用户空间需要内存 拷贝,需要拷贝数据,所以效率低. 2)为了在多个进 ...
- linux 进程间通信 共享内存 shmat
系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件(这是通过shm ...
- linux 进程间通信 共享内存 mmap
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反 ...
- win32下进程间通信——共享内存
一.引言 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...
随机推荐
- [转载+原创]Emgu CV on C# (六) —— Emgu CV on Canny边缘检测
Canny边缘检测也是一种边缘检测方法,本文介绍了Canny边缘检测的函数及其使用方法,并利用emgucv方法将轮廓检测解算的结果与原文进行比较. 图像的边缘检测的原理是检测出图像中所有灰度值变化较大 ...
- System.IO.StreamWriter
string path = @"D:\a.txt"; System.IO.StreamWriter swOut = new System.IO.StreamWriter(path, ...
- iOS$299企业账号In House ipa发布流程
1.在Mac系统中进入“钥匙串访问”,选择“钥匙串访问”-“证书助理”-“从证书颁发机构请求证书”. 填写前两项,并保存在本地. 2.登录https://developer.apple.com,进入i ...
- linux 下 安装 rpm 格式 的 mysql
在Linux操作系统下,安装MYSQL有两种方式: 一种tar安装方式, 另外一种是rpm安装方式. 这两种安装方式有什么区别呢?尽管我们在Linux下常用tar来压缩/解压缩文件,但MYSQL的ta ...
- c++ 获取本地ip地址
最终版本:采用指针传参数,不使用别名形式. #include <unistd.h> #include <netdb.h> //gethostbyname #include &l ...
- CodeForces 173B Chamber of Secrets 二分图+最短路
题目链接: http://codeforces.com/problemset/problem/173/B 题意: 给你一个n*m的地图,现在有一束激光从左上角往左边射出,每遇到‘#’,你可以选择光线往 ...
- ubuntu中磁盘挂载与卸载
问题描述: ubuntu中磁盘的挂载和卸载 问题解决: (1)ubuntu中磁盘挂载 注: 如上所示,使用命令df查看磁盘使用情况 ...
- Oracle 一次执行多条语句
在.Net使用多次方法一次执行多条语句都不成功, 百度了许久才找到正确的解决方案. Oracle执行多条语句的时候 不能有物理换行 写法对比: 如下写法是不成功. begin into t_test ...
- Scrum敏捷开发简介
Agile 敏捷开发实践中,强调团队的自我管理.在 Scrum 中,自我团队管理体现在每天的 Scrum 会议中和日常的协同工作,在每天的 Scrum 例会中,团队成员一般回答一下几个问题 : 昨天完 ...
- 一个很吊的swing循环生成窗口。
import javax.swing.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; publi ...