• 利用QSystemSemaphore和QSharedMemory实现进程间通讯


    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 = 0);
        ~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(1024);
    }
     
    QSystemSemaphore MainWindow::m_lockSrc(QString("lockSrc"), 1, QSystemSemaphore::Create);
    QSystemSemaphore MainWindow::m_lockDst(QString("lockDst"), 0, 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 = 0);
        ~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() / 10, height()/10, width() * 0.8, 20);
    }

    thrd.h

    #pragma once
     
    #include <qthread.h>
    #include <qsystemsemaphore.h>
    #include <qsharedmemory.h>
     
    class thrd : public QThread
    {
        Q_OBJECT
    public:
        thrd(QObject * parent = 0);
        ~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"), 1, QSystemSemaphore::Open);
    QSystemSemaphore thrd::m_lockDst(QString("lockDst"), 0, QSystemSemaphore::Open);
     
    void thrd::run()
    {
        while(true)
        {
            read();
            msleep(1000);
        }
    }
     
    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,0,m_mem.size());  
            m_mem.unlock();  
      
            m_lockSrc.release();  
          
     
            QByteArray qba = text.toLatin1();
            emit sigMsg(qba);
        }
    }  

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

  • 相关阅读:
    git push要输入密码问题
    excel换行
    React的diff算法
    https的通信过程
    一道面试题的分析
    Mac将应用拖入Finder工具栏
    React获取组件实例
    Warning: Received `false` for a non-boolean attribute `xxx`.
    warning: React does not recognize the xxx prop on a DOM element
    webpack开发模式和生产模式设置及不同环境脚本执行
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/11063805.html
Copyright © 2020-2023  润新知