https://blog.csdn.net/liji_digital/article/details/70547082

线程间的通讯可以由QSemaphore调控,以保证各个线程对同一资源的访问不冲突

但是进程间的协调就不能利用QSemaphore,而要利用QSystemSemaphore

此外,在同一进程内的各个线程之间可以用信号-槽机制通信但是进程之间就不可以了。取而代之的是QSharedMemory

下面的两个程序test_process和ProcessClient运行在不同的进程中。前者为主进程,后者为子进程。

主进程利用QProcess::start()启动子进程。QProcess::start(QString())的作用与在命令行输入命令类似。

start的输入参数可以是一个exe文件的名字。这个exe文件在另一个进程中运行。当主进程结束,exe所在的子进程也随之结束。

先看主进程的代码:

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow>
#include <QProcess>
#include <qfile.h>
#include <qsystemsemaphore.h>
#include <qsharedmemory.h> namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = );
~MainWindow(); QProcess m_Proc; QSharedMemory m_mem; static QSystemSemaphore m_lockSrc;
static QSystemSemaphore m_lockDst; void init();
QString read();
void write();
public slots:
void OnClickOK(void);
void OnRecvProc(void);
void OnClickSend(void);
private:
Ui::MainWindow *ui;
};

在头文件中,我定义了主进程向子进程写入数据的函数write(),也定义了读出子进程数据的函数read()。在实际应用中,我只用到了write()。

cpp文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <qbuffer.h> MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this); QObject::connect(&m_Proc, SIGNAL(readyRead()), this, SLOT(OnRecvProc()));
QObject::connect(ui->BtnOK, SIGNAL(clicked()), this, SLOT(OnClickOK()));
QObject::connect(ui->BtnSend, SIGNAL(clicked()), this, SLOT(OnClickSend())); init();
} MainWindow::~MainWindow()
{
delete ui;
} void MainWindow::init()
{
m_mem.setKey(QString("sharedMem"));
if (m_mem.isAttached())
{
m_mem.detach();
}
m_mem.create();
} QSystemSemaphore MainWindow::m_lockSrc(QString("lockSrc"), , QSystemSemaphore::Create);
QSystemSemaphore MainWindow::m_lockDst(QString("lockDst"), , QSystemSemaphore::Create); void MainWindow::OnClickOK(void)
{
QString qstrCmd = ui->lineEdit->text();
m_Proc.start(qstrCmd);
} void MainWindow::OnClickSend(void)
{
write();
} void MainWindow::OnRecvProc(void)
{
QByteArray qba = m_Proc.readAll();
QString qstrFeedBack(qba); ui->textEdit->setText(qstrFeedBack);
} QString MainWindow::read()
{
QBuffer buffer;
QDataStream in(&buffer);
QString text; m_mem.lock();
buffer.setData((char*)m_mem.constData(), m_mem.size());
buffer.open(QBuffer::ReadOnly);
in >> text;
m_mem.unlock();
qDebug() << "WriteSharedMemory:: Read:" << text;
return text;
} void MainWindow::write( )
{
QBuffer buffer;
buffer.open( QBuffer::ReadWrite );
QDataStream out( &buffer );
QString text = ui->lineEdit->text();
out << text;
int size = buffer.size(); if(m_mem.size()<size)
{
qDebug() << "共享内存空间不够!";
return ;
} if(m_lockSrc.acquire())
{
// Write into the shared memory
m_mem.lock();
char *to = (char*)m_mem.data();
const char *from = buffer.data().data();
memcpy( to, from, qMin( m_mem.size(), size ) );
m_mem.unlock();
m_lockDst.release(); qDebug() << "WriteSharedMemory:: Write:" << text;
}
}

再看子进程。它包括两个类:Client和thrd。本来只要client一个类即可接收主线程发来的数据。但是实验发现那样会很卡顿。所以建立一个QThread的派生类--thrd。thrd负责接收主线程的数据。收到后,再利用信号槽机制传给Client,显示出来。通过开启一个线程的方式避免卡顿。
先看Client头文件:

#pragma once

#include <QWidget>
#include <qlineedit.h>
#include <QResizeEvent>
#include "thrd.h" class Client : public QWidget
{
Q_OBJECT public:
Client(QWidget *parent = );
~Client(); thrd m_thrd;
QLineEdit * m_pEdt;
public slots:
void OnRecv(QByteArray);
protected:
void resizeEvent(QResizeEvent *);
};
#include "client.h"
#include <QDebug>
#include <qbuffer.h>
#include <QMessageBox> Client::Client(QWidget *parent)
: QWidget(parent)
{
QMessageBox msg;
msg.setText("start");
msg.exec(); m_pEdt = new QLineEdit(this);
QObject::connect(&m_thrd, SIGNAL(sigMsg(QByteArray)), this, SLOT(OnRecv(QByteArray))); m_thrd.start();
} Client::~Client()
{
m_thrd.terminate();
} void Client::OnRecv(QByteArray qba)
{ m_pEdt->setText(QString(qba));
} void Client::resizeEvent(QResizeEvent *e)
{
m_pEdt->setGeometry(width() / , height()/, width() * 0.8, );
}

thrd.h

#pragma once

#include <qthread.h>
#include <qsystemsemaphore.h>
#include <qsharedmemory.h> class thrd : public QThread
{
Q_OBJECT
public:
thrd(QObject * parent = );
~thrd(); static QSystemSemaphore m_lockSrc;
static QSystemSemaphore m_lockDst;
QSharedMemory m_mem;
void read();
signals:
void sigMsg(QByteArray);
protected:
void run();
};

thrd.cpp

#include "thrd.h"
#include <qbuffer.h>
#include <qdatastream.h> thrd::thrd(QObject * parent) : QThread(parent)
{
m_mem.setKey(QString("sharedMem"));
} thrd::~thrd()
{
} QSystemSemaphore thrd::m_lockSrc(QString("lockSrc"), , QSystemSemaphore::Open);
QSystemSemaphore thrd::m_lockDst(QString("lockDst"), , QSystemSemaphore::Open); void thrd::run()
{
while(true)
{
read();
msleep();
}
} void thrd::read()
{
if(m_mem.isAttached())
{
//qDebug() << "ReadSharedMemory:: haved attached.";
}
else
{
if(!m_mem.attach())
{
QSharedMemory::SharedMemoryError m = m_mem.error();
return; }
else
{
//qDebug() << "ReadSharedMemory:: attach success.";
}
} QBuffer buffer;
QDataStream in(&buffer);
QString text; if(m_lockDst.acquire())
{
m_mem.lock();
buffer.setData((char*)m_mem.constData(), m_mem.size());
buffer.open(QBuffer::ReadOnly);
in >> text;
//清空缓存
char* to = (char*)m_mem.data();
memset(to,,m_mem.size());
m_mem.unlock(); m_lockSrc.release(); QByteArray qba = text.toLatin1();
emit sigMsg(qba);
}
}

子进程的共享内存QSharedMemory必须使用主进程的共享内存一样的名字,并且要使用同名的信号量。但使用时,只要open即可,不需要create。

利用QSystemSemaphore和QSharedMemory实现进程间通讯的更多相关文章

  1. .Net 利用消息在进程间通讯实现进程互操作

    有时候我们会遇到需要在两个进程间通过某种方式实现互操作,方法有很多,例如你可以尝试让两个进程持续监视一个外部文件,由此文件记录各自进程的数据:还有可以使用网络端口实现进程间通讯.共享一片内存区域记录及 ...

  2. QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开     本文地址:h ...

  3. win32进程间通讯--共享内存

    小白一枚,如有不对,请各位大神多多指教! 最近看了看win32进程间通讯.简单写了写利用共享内存实现进程间通讯 使用共享内存实现进程间通讯: 1.在WM_CREATE消息下创建文件映射内核对象 hMa ...

  4. Android进阶笔记04:Android进程间通讯(IPC)之Messenger

    一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...

  5. Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  6. C#进程间通讯技术-整理。

    原文:C#进程间通讯技术-整理. 扩展阅读:http://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html 一.进程间通讯的方式 1) ...

  7. 管道实现进程间通讯 、WaitNamedPipe

    一.管道实现进程间通讯 主要的理论知识 1.什么是管道以及分类 管道是两个头的东西,每一个头各连接一个进程或者同一个进程的不同代码,依照管道的类别分有两种管道,匿名的和命名的:依照管道的传输方向分也能 ...

  8. Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  9. Node.js - 阿里Egg的多进程模型和进程间通讯

    前言 最近用Egg作为底层框架开发项目,好奇其多进程模型的管理实现,于是学习了解了一些东西,顺便记录下来.文章如有错误, 请轻喷 为什么需要多进程 伴随科技的发展, 现在的服务器基本上都是多核cpu的 ...

随机推荐

  1. PAT(B) 1093 字符串A+B(Java和C)

    题目链接:1093 字符串A+B (20 point(s)) 题目描述 给定两个字符串 A 和 B,本题要求你输出 A+B,即两个字符串的并集.要求先输出 A,再输出 B,但重复的字符必须被剔除. 输 ...

  2. WUSTOJ 1323: Repeat Number(Java)规律统计

    题目链接:1323: Repeat Number Description Definition: a+b = c, if all the digits of c are same ( c is mor ...

  3. PAT甲级题分类汇编——图

    本文为PAT甲级分类汇编系列文章. 图,就是层序遍历和Dijkstra这一套,#include<queue> 是必须的. 题号 标题 分数 大意 时间 1072 Gas Station 3 ...

  4. Scala 算法案例

    移除第一个负数之后的所有负数 // 构建数组 val a = ArrayBuffer[Int]() a += (1, 2, 3, 4, 5, -1, -3, -5, -9) // 每发现一个第一个负数 ...

  5. session和cookie有什么区别?

    1.存储位置不同 cookie的数据信息存放在客户端浏览器上. session的数据信息存放在服务器上. 2.存储容量不同 单个cookie保存的数据<=4KB,一个站点最多保存20个Cooki ...

  6. THUPC2019/CTS2019/APIO2019/PKUSC2019游记

    THUPC2019/CTS2019/APIO2019/PKUSC2019游记 5.10 中铺,火车好晃啊 5.11 打了THUPC2019的练习赛,华容道好评(四个小兵,杠鸭!) 5.12 打了THU ...

  7. 监听iframe加载完成

    用 @load="loading" 在Vue里面写了一个界面,有一个iframe标签, iframe加载其他网站, <iframe @load="loading&q ...

  8. Jmeter学习笔记(五)——dubbo接口测试

    一.什么是dubbo接口 Dubbo 接口是阿里巴巴开源的致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,dubbo框架告别了传统的web service的服务模式,进而改用 ...

  9. iOS滤镜功能

    一.iOS自带滤镜 1.CoreImage 使用苹果自带的CoreImage框架对图片进行处理,用CoreImage框架里的CIFilter对图片进行滤镜处理, 首先我们应该了解下CoreImage框 ...

  10. springcloud工程建立 父工程+公用子模块+微服务提供模块

    建立 Java Working Set:工程多的时候可以展开收缩,方便管理 切换到Package Explorer视图,并点击视图右侧下箭头,选择Working Sets,如下图: 建立父工程,将后续 ...