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

Posted xiangtingshen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用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。

 

以上是关于利用QSystemSemaphore和QSharedMemory实现进程间通讯的主要内容,如果未能解决你的问题,请参考以下文章

如何利用ArcGis生成TPK

CORS漏洞利用检测和利用方式

CPU负载和利用率

利用cgroup限制cpu和memory利用率

RL - 09 探索与利用

2022年土地利用规划之平时作业二