一、进程通信的介绍

Qt提供了多种方法在Qt应用程序中实现进程间通信IPC(Inter-Process Communication)。

1)TCP/IP
跨平台的Qt Network模块提供了众多的类来实现网络编程。它提供了高层的类(比如QNetworkAccessManager等)来使用指定的应用程序级协议,也提供了较低层的类(例如,QTcpSocket、QTcpServer和QSslSocket)来实现相关协议。

2)共享内存
QSharedMemory是跨平台的共享内存类,提供了访问操作系统共享内存的实现。
它允许多个线程和进程安全地访问共享内存段。此外,QSystemSemaphore可用于控
制系统的共享资源的访问以及进程间通信。

3)D-Bus
QtD-Bus模块是一个Unix库,可以使用D-Bus协议来实现进程间通信。它将Qt
的信号和槽机制扩展到了P℃层面,允许从一个进程发射的信号关联到另一个进程的
槽上。可以在帮助中查看DBus关键字,对应的文档中有其详细的介绍。

4)QProcess

上一章介绍过

5)会话管理
在Linux/X11平台上,Qt提供了对会话管理的支持,回话允许时间传播到进程。例如,当关机时通知进程或程序,从而可以执行一些相关的操作。

二、共享内存的实例

)新建Qt Widgets应用,名称为myIPC,基类选择QDialog,类名为Dialog。完成后进入设计模式,向界面中放入两个Push Button部件和一个Label部件。将一个按钮的显示文本更改为“从文件中加载图片”,将其objectName属性更改为pushButtonLoadFromFile,将另一个按钮的显示文本更改为“从共享内存显示图片”,将其objectName属性更改为pushButtonLoadFromSharedMemory。

qprocess start后怎么退出 qprocess cmd_开发语言

 

然后进入dialog.h文件,先添加头文件包含:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QSharedMemory>

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    QSharedMemory sharedMemory;

    void detach();

public slots:
    void loadFromFile();
    void loadFromMemory();
private slots:
    void on_pushButtonLoadFromFile_clicked();
    void on_pushButtonLoadFromSharedMemory_clicked();
};

#endif // DIALOG_H

cpp文件

#include "dialog.h"
#include "ui_dialog.h"
#include <QFileDialog>
#include <QBuffer>
#include <QDebug>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    //在共享内存以前,需要先为其制定一个key,系统用它来作为底层共享内存段的标识。这个key可以是任意的字符串
    sharedMemory.setKey("QSharedMemoryExample");
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::loadFromFile()
{
    //判断该进程是否已经连接到共享内存段,如果是,就将该进程与共享内存段进行分离。
    if(sharedMemory.isAttached())
        detach();

    ui->label->setText(tr("选择一个图片文件!"));
    QString fileName = QFileDialog::getOpenFileName(0,QString(),QString(),tr("Images(*.png *.jpg)"));
    QImage image;
    if(!image.load(fileName))
    {
        ui->label->setText(tr("选择的文件不是图片,请选择图片文件"));
        return;
    }
    ui->label->setPixmap((QPixmap::fromImage(image)));
    //将图片加载到共享内存
    QBuffer buffer;
    //将图片暂存到buffer中
    buffer.open(QBuffer::ReadWrite);
    //获取图片数据的指针
    QDataStream out(&buffer);
    out<<image;
    //获取图片的大小
    int size = buffer.size();
    //创建指定大小的共享内存段
    if(!sharedMemory.create(size))
    {
        ui->label->setText(tr("无法创建共享内存段"));//
        return;
    }
    //在共享内存段的操作时,需要先加锁
    sharedMemory.lock();
    char * to = (char*)sharedMemory.data();
    const char * from = buffer.data().data();
    memcpy(to,from,qMin(sharedMemory.size(),size));
    //解锁
    sharedMemory.unlock();

    //如果将最后一个连接在共享内存段上的进程进行分离,那么系统会释放共享内存段。
}

void Dialog::loadFromMemory()
{
    //将进程连接到共享内存段
    if(!sharedMemory.attach())
    {
        ui->label->setText(tr("无法连接到共享内存段,\n"
                              "请先加载一张图片!"));
        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();
    ui->label->setPixmap(QPixmap::fromImage(image));

}

void Dialog::detach()
{
    if(!sharedMemory.detach())
    {
        ui->label->setText(tr("无法从共享内存中分离"));
    }
}

void Dialog::on_pushButtonLoadFromFile_clicked()
{
    loadFromFile();
}

void Dialog::on_pushButtonLoadFromSharedMemory_clicked()
{
    loadFromMemory();
}

现在运行两次程序,在一个运行的实例上单击“从文件中加载图片”按钮,然后选择一张图片。在第二个运行的实例上单击“从共享内存显示图片”按钮,这时便会显示第一个实例中加载的图片,效果如图所示。 

qprocess start后怎么退出 qprocess cmd_Memory_02

qprocess start后怎么退出 qprocess cmd_共享内存_03