QT使用共享內(nèi)存實現(xiàn)進程間通訊
QSharedMemory:如果兩個進程運行在同一臺機器上,且對性能要求非常高(如實時數(shù)據(jù)共享、圖像渲染等),建議使用共享內(nèi)存。
優(yōu)點:
- 高性能: 共享內(nèi)存是進程間通信的最快方式之一,因為數(shù)據(jù)直接在內(nèi)存中共享,不需要經(jīng)過內(nèi)核的系統(tǒng)調(diào)用或網(wǎng)絡(luò)協(xié)議棧。
- 低延遲: 由于數(shù)據(jù)直接在內(nèi)存中傳遞,延遲非常低,適合需要高性能的場景(如實時數(shù)據(jù)處理、圖像渲染等)。
- 簡單數(shù)據(jù)共享: 適合兩個進程需要頻繁訪問相同數(shù)據(jù)的場景。
設(shè)計思路
共享內(nèi)存區(qū):用于存儲數(shù)據(jù)。
互斥量:用于保護共享內(nèi)存區(qū),防止多個進程同時訪問導(dǎo)致數(shù)據(jù)不一致。
信號量:用于通知對方有數(shù)據(jù)可用。
服務(wù)器實現(xiàn)
頭文件
#ifndef SHAREDMEMORYSERVICE_H #define SHAREDMEMORYSERVICE_H #include <QObject> #include <QSharedMemory> #include <QBuffer> #include <QDataStream> #include <QDebug> #include <QThread> #include <QSystemSemaphore> class SharedMemoryService : public QObject { Q_OBJECT public: explicit SharedMemoryService(QObject* parent = nullptr); ~SharedMemoryService(); // 向共享內(nèi)存中寫入數(shù)據(jù) bool writeToSharedMemory(const QByteArray& data); signals: // 當(dāng)讀取到共享內(nèi)存中的數(shù)據(jù)時發(fā)出信號 void signalRead(QBuffer& buffer); private slots: // 檢查共享內(nèi)存中的數(shù)據(jù) void checkSharedMemory(); private: std::shared_ptr<QSharedMemory> m_sharedMemory; // 共享內(nèi)存 std::shared_ptr<QSystemSemaphore> m_semaphoreClient; // 信號量 - 客戶端發(fā)送 std::shared_ptr<QSystemSemaphore> m_semaphoreService; // 信號量- 服務(wù)器發(fā)送 bool m_bCreate = false; // 是否創(chuàng)建成功 bool m_bExit = false; // 是否退出 QThread m_listenThread; // 監(jiān)聽線程 }; #endif // SHAREDMEMORYSERVICE_H
cpp
#include "SharedMemoryService.h" SharedMemoryService::SharedMemoryService(QObject* parent) : QObject(parent), m_sharedMemory(std::make_shared<QSharedMemory>("MySharedMemoryKey_XXX")), m_semaphoreClient(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX", 0)), m_semaphoreService(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX2", 0)) { // 創(chuàng)建共享內(nèi)存,大小為1024字節(jié) if (!m_sharedMemory->create(1024)) { qDebug() << "無法創(chuàng)建共享內(nèi)存:" << m_sharedMemory->errorString(); return; } m_bCreate = true; // 移動監(jiān)聽線程到單獨的線程中 QObject::connect(&m_listenThread, &QThread::started, this, &SharedMemoryService::checkSharedMemory, Qt::DirectConnection); m_listenThread.start(); } SharedMemoryService::~SharedMemoryService() { m_bExit = true; m_semaphoreClient->release(1); // 停止監(jiān)聽線程 m_listenThread.quit(); m_listenThread.wait(); } void SharedMemoryService::checkSharedMemory() { if (!m_bCreate || !m_sharedMemory->isAttached()) return; while (true) { // 等待信號量 if (m_semaphoreClient->acquire()) { if (m_bExit) { break; } if (m_sharedMemory->lock()) { // 讀取共享內(nèi)存中的數(shù)據(jù) QBuffer buffer; buffer.setData((char*)m_sharedMemory->data(), m_sharedMemory->size()); buffer.open(QIODevice::ReadOnly); // 如果共享內(nèi)存中有數(shù)據(jù),則發(fā)出信號 if (buffer.size() > 0) { emit signalRead(buffer); // 清空共享內(nèi)存內(nèi)容 memset(m_sharedMemory->data(), 0, m_sharedMemory->size()); } // 解鎖共享內(nèi)存 m_sharedMemory->unlock(); } } } } bool SharedMemoryService::writeToSharedMemory(const QByteArray& data) { if (!m_bCreate || !m_sharedMemory->isAttached()) { qDebug() << "共享內(nèi)存未創(chuàng)建或未附加"; return false; } if (m_sharedMemory->lock()) { // 將數(shù)據(jù)寫入共享內(nèi)存 memcpy(m_sharedMemory->data(), data.data(), qMin(data.size(), m_sharedMemory->size())); // 釋放鎖 m_sharedMemory->unlock(); // 增加信號量計數(shù),通知監(jiān)聽線程有數(shù)據(jù)可用 m_semaphoreService->release(1); return true; } qDebug() << "無法鎖定共享內(nèi)存"; return false; }
調(diào)用
/// 創(chuàng)建共享內(nèi)存 void MainWindow::slotCrateBtn() { if (m_service) { return; } ui->btnCreate->setEnabled(false); m_service = new SharedMemoryService(); // 連接信號槽,監(jiān)聽共享內(nèi)存中的數(shù)據(jù) QObject::connect(m_service, &SharedMemoryService::signalRead, this, &MainWindow::slotRecv, Qt::DirectConnection); } /// 發(fā)送內(nèi)容 void MainWindow::slotSendBtn() { if (m_service == nullptr) { return; } // 向共享內(nèi)存中寫入數(shù)據(jù) QByteArray data = ui->textEditSend->toPlainText().toLocal8Bit(); if (m_service->writeToSharedMemory(data)) { qDebug() << "數(shù)據(jù)已成功寫入共享內(nèi)存"; } else { qDebug() << "寫入共享內(nèi)存失敗"; } } /// 收到數(shù)據(jù) void MainWindow::slotRecv(QBuffer& buffer) { QString text = buffer.data(); if (text.isEmpty()) { return; } qDebug() << "接收到共享內(nèi)存中的數(shù)據(jù):" << text; ui->textEdit->append(text); }
客戶端實現(xiàn)
頭文件
#ifndef SHAREDMEMORYCLIENT_H #define SHAREDMEMORYCLIENT_H #include <QObject> #include <QSharedMemory> #include <QBuffer> #include <QDataStream> #include <QDebug> #include <QThread> #include <QSystemSemaphore> #include <cstdio> #include <iostream> #include <list> #include <memory> #include <string> class SharedMemoryClient : public QObject { Q_OBJECT public: explicit SharedMemoryClient(QObject* parent = nullptr); ~SharedMemoryClient(); // 向共享內(nèi)存中寫入數(shù)據(jù) bool writeToSharedMemory(const QByteArray& data); signals: // 當(dāng)讀取到共享內(nèi)存中的數(shù)據(jù)時發(fā)出信號 void signalRead(QBuffer& buffer); private slots: // 處理共享內(nèi)存中的數(shù)據(jù) void processSharedMemory(); private: std::shared_ptr<QSharedMemory> m_sharedMemory; // 共享內(nèi)存 std::shared_ptr<QSystemSemaphore> m_semaphoreClient; // 信號量 - 客戶端發(fā)送 std::shared_ptr<QSystemSemaphore> m_semaphoreService; // 信號量- 服務(wù)器發(fā)送 bool m_bCreate = false; // 是否創(chuàng)建成功 bool m_bExit = false; // 是否退出 QThread m_listenThread; // 監(jiān)聽線程 }; #endif // SHAREDMEMORYCLIENT_H
cpp
#include "SharedMemoryClient.h" SharedMemoryClient::SharedMemoryClient(QObject* parent) : QObject(parent), m_sharedMemory(std::make_shared<QSharedMemory>("MySharedMemoryKey_XXX")), m_semaphoreClient(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX", 0)), m_semaphoreService(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX2", 0)) { if (!m_sharedMemory->attach()) { qDebug() << "無法附加到共享內(nèi)存:" << m_sharedMemory->errorString(); return; } m_bCreate = true; // 將處理方法移動到監(jiān)聽線程中 moveToThread(&m_listenThread); connect(&m_listenThread, &QThread::started, this, &SharedMemoryClient::processSharedMemory, Qt::DirectConnection); // 啟動監(jiān)聽線程 m_listenThread.start(); } SharedMemoryClient::~SharedMemoryClient() { m_bExit = true; m_semaphoreService->release(1); // 停止監(jiān)聽線程 m_listenThread.quit(); m_listenThread.wait(); } void SharedMemoryClient::processSharedMemory() { while (true) { if (m_semaphoreService->acquire()) { if (m_bExit) { break; } if (!m_bCreate || !m_sharedMemory->isAttached()) continue; // 鎖定共享內(nèi)存 if (m_sharedMemory->lock()) { // 檢查共享內(nèi)存是否有數(shù)據(jù) QBuffer buffer; buffer.setData((char*)m_sharedMemory->data(), m_sharedMemory->size()); buffer.open(QIODevice::ReadOnly); // 如果共享內(nèi)存中有數(shù)據(jù),則發(fā)出信號 if (buffer.size() > 0) { emit signalRead(buffer); // 清空共享內(nèi)存內(nèi)容 memset(m_sharedMemory->data(), 0, m_sharedMemory->size()); } // 解鎖共享內(nèi)存 m_sharedMemory->unlock(); } } } } bool SharedMemoryClient::writeToSharedMemory(const QByteArray& data) { if (!m_bCreate || !m_sharedMemory->isAttached()) { qDebug() << "共享內(nèi)存未創(chuàng)建或未附加"; return false; } // 鎖定共享內(nèi)存 if (m_sharedMemory->lock()) { // 將數(shù)據(jù)寫入共享內(nèi)存 memcpy(m_sharedMemory->data(), data.data(), qMin(data.size(), m_sharedMemory->size())); // 解鎖共享內(nèi)存 m_sharedMemory->unlock(); // 釋放信號量,通知監(jiān)聽線程 m_semaphoreClient->release(1); return true; } qDebug() << "無法鎖定共享內(nèi)存"; return false; }
調(diào)用
/// 連接共享內(nèi)存 void MainWindow::slotCrateBtn() { if (m_client) { return; } ui->btnCreate->setEnabled(false); m_client = new SharedMemoryClient(); // 連接信號槽,監(jiān)聽共享內(nèi)存中的數(shù)據(jù) QObject::connect(m_client, &SharedMemoryClient::signalRead, this, &MainWindow::slotRecv, Qt::DirectConnection); } /// 發(fā)送內(nèi)容 void MainWindow::slotSendBtn() { if (m_client == nullptr) { return; } // 向共享內(nèi)存中寫入數(shù)據(jù) QByteArray data = ui->textEditSend->toPlainText().toLocal8Bit(); if (m_client->writeToSharedMemory(data)) { qDebug() << "數(shù)據(jù)已成功寫入共享內(nèi)存"; } else { qDebug() << "寫入共享內(nèi)存失敗"; } } /// 收到數(shù)據(jù) void MainWindow::slotRecv(QBuffer& buffer) { QString text = buffer.data(); if (text.isEmpty()) { return; } qDebug() << "接收到共享內(nèi)存中的數(shù)據(jù):" << text; ui->textEdit->append(text); }
運行效果
以上就是QT使用共享內(nèi)存實現(xiàn)進程間通訊的詳細內(nèi)容,更多關(guān)于QT進程間通訊的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
利用反射獲得類的public static/const成員的值實例
下面小編就為大家?guī)硪黄梅瓷浍@得類的public static/const成員的值實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12淺談Windows系統(tǒng)下C語言編程中Glib庫的使用
這篇文章主要介紹了Windows系統(tǒng)下C語言編程中Glib庫的使用,Glib庫在多線程編程中經(jīng)??梢杂玫?需要的朋友可以參考下2016-02-02