最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

QT使用共享內存實現(xiàn)進程間通訊

 更新時間:2024年12月13日 09:17:22   作者:hss2799  
這篇文章主要為大家詳細介紹了QT如何使用共享內存實現(xiàn)進程間通訊,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

QSharedMemory:如果兩個進程運行在同一臺機器上,且對性能要求非常高(如實時數(shù)據共享、圖像渲染等),建議使用共享內存。

優(yōu)點:

  • 高性能: 共享內存是進程間通信的最快方式之一,因為數(shù)據直接在內存中共享,不需要經過內核的系統(tǒng)調用或網絡協(xié)議棧。
  • 低延遲: 由于數(shù)據直接在內存中傳遞,延遲非常低,適合需要高性能的場景(如實時數(shù)據處理、圖像渲染等)。
  • 簡單數(shù)據共享: 適合兩個進程需要頻繁訪問相同數(shù)據的場景。

設計思路

共享內存區(qū):用于存儲數(shù)據。

互斥量:用于保護共享內存區(qū),防止多個進程同時訪問導致數(shù)據不一致。

信號量:用于通知對方有數(shù)據可用。

服務器實現(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();

    // 向共享內存中寫入數(shù)據
    bool writeToSharedMemory(const QByteArray& data);

signals:
    // 當讀取到共享內存中的數(shù)據時發(fā)出信號
    void signalRead(QBuffer& buffer);

private slots:
    // 檢查共享內存中的數(shù)據
    void checkSharedMemory();

private:
    std::shared_ptr<QSharedMemory> m_sharedMemory; // 共享內存
    std::shared_ptr<QSystemSemaphore> m_semaphoreClient; // 信號量 - 客戶端發(fā)送
    std::shared_ptr<QSystemSemaphore> m_semaphoreService; // 信號量- 服務器發(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)建共享內存,大小為1024字節(jié)
    if (!m_sharedMemory->create(1024)) {
        qDebug() << "無法創(chuàng)建共享內存:" << 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()) 
            {
                // 讀取共享內存中的數(shù)據
                QBuffer buffer;
                buffer.setData((char*)m_sharedMemory->data(), m_sharedMemory->size());
                buffer.open(QIODevice::ReadOnly);

                // 如果共享內存中有數(shù)據,則發(fā)出信號
                if (buffer.size() > 0) {
                    emit signalRead(buffer);

                    // 清空共享內存內容
                    memset(m_sharedMemory->data(), 0, m_sharedMemory->size());
                }

                // 解鎖共享內存
                m_sharedMemory->unlock();
            }
        }
    }
}

bool SharedMemoryService::writeToSharedMemory(const QByteArray& data)
{
    if (!m_bCreate || !m_sharedMemory->isAttached())
    {
        qDebug() << "共享內存未創(chuàng)建或未附加";
        return false;
    }

    if (m_sharedMemory->lock()) {
        // 將數(shù)據寫入共享內存
        memcpy(m_sharedMemory->data(), data.data(), qMin(data.size(), m_sharedMemory->size()));

        // 釋放鎖
        m_sharedMemory->unlock();

        // 增加信號量計數(shù),通知監(jiān)聽線程有數(shù)據可用
        m_semaphoreService->release(1);

        return true;
    }

    qDebug() << "無法鎖定共享內存";
    return false;
}

調用

/// 創(chuàng)建共享內存
void MainWindow::slotCrateBtn()
{
    if (m_service)
    {
        return;
    }
    ui->btnCreate->setEnabled(false);
    m_service = new SharedMemoryService();
    // 連接信號槽,監(jiān)聽共享內存中的數(shù)據
    QObject::connect(m_service, &SharedMemoryService::signalRead, this, &MainWindow::slotRecv, Qt::DirectConnection);
}

/// 發(fā)送內容
void MainWindow::slotSendBtn()
{
    if (m_service == nullptr)
    {
        return;
    }    
    // 向共享內存中寫入數(shù)據
    QByteArray data = ui->textEditSend->toPlainText().toLocal8Bit();
    if (m_service->writeToSharedMemory(data))
    {
        qDebug() << "數(shù)據已成功寫入共享內存";
    }
    else
    {
        qDebug() << "寫入共享內存失敗";
    }
}

/// 收到數(shù)據
void MainWindow::slotRecv(QBuffer& buffer)
{
    QString text = buffer.data();
    if (text.isEmpty())
    {
        return;
    }
    qDebug() << "接收到共享內存中的數(shù)據:" << 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();

    // 向共享內存中寫入數(shù)據
    bool writeToSharedMemory(const QByteArray& data);

signals:
    // 當讀取到共享內存中的數(shù)據時發(fā)出信號
    void signalRead(QBuffer& buffer);

private slots:
    // 處理共享內存中的數(shù)據
    void processSharedMemory();

private:
    std::shared_ptr<QSharedMemory> m_sharedMemory; // 共享內存
    std::shared_ptr<QSystemSemaphore> m_semaphoreClient; // 信號量 - 客戶端發(fā)送
    std::shared_ptr<QSystemSemaphore> m_semaphoreService; // 信號量- 服務器發(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() << "無法附加到共享內存:" << 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;

            // 鎖定共享內存
            if (m_sharedMemory->lock())
            {
                // 檢查共享內存是否有數(shù)據
                QBuffer buffer;
                buffer.setData((char*)m_sharedMemory->data(), m_sharedMemory->size());
                buffer.open(QIODevice::ReadOnly);

                // 如果共享內存中有數(shù)據,則發(fā)出信號
                if (buffer.size() > 0)
                {
                    emit signalRead(buffer);

                    // 清空共享內存內容
                    memset(m_sharedMemory->data(), 0, m_sharedMemory->size());
                }

                // 解鎖共享內存
                m_sharedMemory->unlock();
            }
        }
    }
}

bool SharedMemoryClient::writeToSharedMemory(const QByteArray& data)
{
    if (!m_bCreate || !m_sharedMemory->isAttached())
    {
        qDebug() << "共享內存未創(chuàng)建或未附加";
        return false;
    }

    // 鎖定共享內存
    if (m_sharedMemory->lock())
    {
        // 將數(shù)據寫入共享內存
        memcpy(m_sharedMemory->data(), data.data(), qMin(data.size(), m_sharedMemory->size()));

        // 解鎖共享內存
        m_sharedMemory->unlock();

        // 釋放信號量,通知監(jiān)聽線程
        m_semaphoreClient->release(1);

        return true;
    }

    qDebug() << "無法鎖定共享內存";
    return false;
}

調用

/// 連接共享內存
void MainWindow::slotCrateBtn()
{
    if (m_client)
    {
        return;
    }
    ui->btnCreate->setEnabled(false);
    m_client = new SharedMemoryClient();
    // 連接信號槽,監(jiān)聽共享內存中的數(shù)據
    QObject::connect(m_client, &SharedMemoryClient::signalRead, this, &MainWindow::slotRecv, Qt::DirectConnection);


}

/// 發(fā)送內容
void MainWindow::slotSendBtn()
{
    if (m_client == nullptr)
    {
        return;
    }
    // 向共享內存中寫入數(shù)據
    QByteArray data = ui->textEditSend->toPlainText().toLocal8Bit();
    if (m_client->writeToSharedMemory(data))
    {
        qDebug() << "數(shù)據已成功寫入共享內存";
    }
    else
    {
        qDebug() << "寫入共享內存失敗";
    }
}
/// 收到數(shù)據
void MainWindow::slotRecv(QBuffer& buffer)
{
    QString text = buffer.data();
    if (text.isEmpty())
    {
        return;
    }
    qDebug() << "接收到共享內存中的數(shù)據:" << text;
    ui->textEdit->append(text);
}

運行效果

以上就是QT使用共享內存實現(xiàn)進程間通訊的詳細內容,更多關于QT進程間通訊的資料請關注腳本之家其它相關文章!

相關文章

  • 使用udp發(fā)送>=128K的消息會報ENOBUFS的錯誤的解決方法

    使用udp發(fā)送>=128K的消息會報ENOBUFS的錯誤的解決方法

    在項目中選擇了unix域的數(shù)據報套接口。在使用過程中碰到了如下,問題:發(fā)送<128K的消息時,客戶、進程可以正常收發(fā)消息;發(fā)送>=128K的消息時,發(fā)送端(sendto)返回ENOBUFS的錯誤。下面小編來詳細說下
    2019-05-05
  • C++設計模式之訪問者模式

    C++設計模式之訪問者模式

    這篇文章主要介紹了C++設計模式之訪問者模式,本文講解了什么是訪問者模式、訪問者模式的UML類圖、訪問者模式的實現(xiàn)代碼等內容,需要的朋友可以參考下
    2014-10-10
  • OpenCV實戰(zhàn)之基于Hu矩實現(xiàn)輪廓匹配

    OpenCV實戰(zhàn)之基于Hu矩實現(xiàn)輪廓匹配

    這篇文章主要介紹了利用C++ OpenCV實現(xiàn)基于Hu矩的輪廓匹配,文中的示例代碼講解詳細,對我們學習OpenCV有一定的幫助,感興趣的可以學習一下
    2022-01-01
  • C語言泛型編程實例教程

    C語言泛型編程實例教程

    這篇文章主要介紹了C語言泛型編程,針對泛型的用法做了深入淺出的實例介紹,是C程序設計中非常實用的技巧,需要的朋友可以參考下
    2014-09-09
  • 詳解C/C++實現(xiàn)各種字符轉換方法合集

    詳解C/C++實現(xiàn)各種字符轉換方法合集

    這篇文章主要為大家詳細介紹了C/C++中實現(xiàn)各種字符轉換的方法,文中的示例代碼講解詳細,對我們學習C++具有一定借鑒價值,需要的可以參考一下
    2022-09-09
  • 基于Qt實現(xiàn)日志打印系統(tǒng)

    基于Qt實現(xiàn)日志打印系統(tǒng)

    這篇文章主要為大家詳細介紹了如何利用Qt開發(fā)一個日志打印系統(tǒng),可以實現(xiàn)打印日志按日期、大小保存,過期刪除,窗口實時顯示日志,網絡傳輸日志遠程調試,需要的可以參考下
    2023-12-12
  • Qt實現(xiàn)簡單UDP通信

    Qt實現(xiàn)簡單UDP通信

    這篇文章主要為大家詳細介紹了Qt實現(xiàn)簡單UDP通信,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Qt學習之容器類的使用教程詳解

    Qt學習之容器類的使用教程詳解

    Qt提供了多個基于模板的容器類,這些類可以用于存儲指定類型的數(shù)據項。本文主要介紹了Qt常用容器類的使用,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-12-12
  • 指針操作數(shù)組的兩種方法(總結)

    指針操作數(shù)組的兩種方法(總結)

    下面小編就為大家?guī)硪黄羔槻僮鲾?shù)組的兩種方法(總結)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 新舊MFC版本實現(xiàn)CEdit透明的2種方法的實例代碼

    新舊MFC版本實現(xiàn)CEdit透明的2種方法的實例代碼

    新舊MFC版本實現(xiàn)CEdit透明的2種方法的實例代碼,需要的朋友可以參考一下
    2013-03-03

最新評論

隆安县| 固阳县| 辽中县| 古交市| 连南| 黔西县| 东阿县| 综艺| 深州市| 余姚市| 清水河县| 上林县| 应用必备| 镇巴县| 揭阳市| 平顶山市| 县级市| 年辖:市辖区| 通河县| 麻城市| 张家川| 滦南县| 灌南县| 扎鲁特旗| 霍山县| 扶绥县| 琼海市| 长寿区| 辽阳县| 大渡口区| 青浦区| 肃宁县| 远安县| 永年县| 东阳市| 邹城市| 七台河市| 修武县| 会同县| 武汉市| 贵德县|