QT開發(三十五)——QT進程間通訊

QT開發(三十五)——QT進程間通訊

    Qt 是一個跨平臺的應用框架,其進程間通訊機制固然可使用所在平臺的進程間通訊機制,如在Windows平臺上的Message機制、共享內存、文件映射、管道、Socket等。其中,Qt對一些許多平臺共有的IPC機制進行了封裝。編程

1、TCP/IP

    其實就是經過網絡模塊實現的IPC。不過Qt對其進行了封裝,並提供了兩個層次的API,包括應用程序級的QNetworkAccessManager, QFtp等和底層的QTcpSocket, QTcpServer, QSslSocket等。網絡



2、QShared Memory(共享內存)

    Qt提供的基於共享內存的IPC有QSharedMemory類和QSystemSemaphore類,QSharedMemory能夠訪問共享內存區域,以及多線程和進程的共享內存區域,而QSystemSemaphore類用於訪問系統共享資源,以實現獨立進程間的通訊。多線程

一、QSharedMemory

    QSharedMemory讀寫內存時,可使用lock()實現同步。若是同步完成,必須使用unlock()爲共享內存區域解鎖。架構

    QSharedMemory可使用attach()訪問共享內存,經過指定參數來設置共享內存的訪問模式。若是使用的是QSharedMemory::ReadOnly模式,則只能經過只讀模式訪問共享內存,若是使用QSharedMemory::ReadWrite模式則能夠經過讀寫模式訪問共享內存。app

    QSharedMemory擁有進程並提供能夠返回共享內存區域指針的成員函數。在共享內存區域,成員函數constData()能夠經過void 類型返回進程正在使用的內存區域指針。建立共享時,QSharedMemory能夠以字節爲單位分配共享內存區域,還能夠經過第二個參數設置函數 attach()提供的模式。框架

    QSharedMemory能夠設置特定共享內存的固定鍵。函數setNativeKey()能夠設置共享內存對象的鍵,setNativeKey()函數使用從屬平臺的共享內存的鍵進行相關設置。使用函數setKey()能夠設置獨立於平臺的鍵。函數setKey()建立與平臺本地鍵(Native Key)映射的鍵。ide

    初始化QSharedMemory時,必須指定一個惟一的標識Key,進程的Key必須保持一致。可使用setKey來設置。函數

二、QSystemSemaphore

    QSystemSemaphore能夠提供普通系統的信號量。信號量使用互斥體,而互斥體只可使用1次鎖定(Block)。所以,QSemaphore類不能對有效資源使用多線程,而QSystemSemaphore類能夠再多進程或多線程中實現。ui

    QSystemSemaphore與QSemaphore類不一樣,能夠訪問多進程。這表示QSystemSemaphore是一個重量級的類。因 此,使用單一線程或進程時,建議使用QSemaphore。得到資源前,成員函數acquire()始終阻塞。函數release()用於釋放資源,且該 函數能夠設置參數。該函數的參數>1時,釋放資源。this

三、QSharedMemory編程流程

共享內存中數據提供方:

A、定義QSharedMemory shareMemory,並設置標誌名shareMemory.setKey();

B、將共享內存與主進程分離 shareMemory.detach()

C、建立共享內存 shareMemory.create()

D、將共享內存上鎖shareMemory.lock()

E、將進程中要共享的數據拷貝到共享內存中;

F、將共享內存解鎖shareMemory.unlock()

共享內存中數據使用方:

A、定義QSharedMemory shareMemory,並設置與共享內存提供方一致的標誌名shareMemory.setKey()。

B、將共享內存上鎖shareMemory.lock();

C、將共享內存與主進程綁定shareMemory.attach(),使主進程能夠訪問共享內存的數據;

D、從共享內存中取數據;

E、使用完後將共享內存解鎖shareMemory.unlock(),並將共享內存與進程分離shareMemory.detach()

四、QSharedMemory使用實例

共享內存數據提供方代碼:

Widget.h文件:

#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include <QSharedMemory>
class Widget : public QWidget
{
    Q_OBJECT
    
public:
    Widget(QWidget *parent = 0);
    ~Widget();
private:
    QSharedMemory sharememory;
private slots:
    void WriteShareMemory();
};
#endif // WIDGET_H

Widget.cpp文件:

#include "Widget.h"
#include <QBuffer>
#include <QDebug>
#include <QDataStream>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    sharememory.setKey("share");
    this->WriteShareMemory();
}
Widget::~Widget()
{
    
}
void Widget::WriteShareMemory()
{
    if(sharememory.isAttached())
    {
        sharememory.detach();
    }
    QBuffer buffer;
    QDataStream out(&buffer);
    buffer.open(QBuffer::ReadWrite);
    buffer.write("hello QT!");
    int size = buffer.size();
    if(!sharememory.create(size))
    {
        qDebug() << sharememory.errorString();
        return ;
    }
    sharememory.lock();
    char *dest = reinterpret_cast<char *>(sharememory.data());
    const char *source = reinterpret_cast<const char *>(buffer.data().data());
    memcpy(dest, source, qMin(size, sharememory.size()));
    sharememory.unlock();
}

Main.cpp文件:

#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

共享內存數據使用方代碼:

Widget.h文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include <QSharedMemory>
class Widget : public QWidget
{
    Q_OBJECT
    
public:
    Widget(QWidget *parent = 0);
    ~Widget();
private:
    QSharedMemory sharememory;
private slots:
    void ReadShareMemory();
};
#endif // WIDGET_H

Widget.cpp文件:

#include "Widget.h"
#include <QBuffer>
#include <QDebug>
#include <QDataStream>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    sharememory.setKey("share");
    this->ReadShareMemory();
}
Widget::~Widget()
{
    
}
void Widget::ReadShareMemory()
{
    if(!sharememory.attach())
    {
        qDebug() << "cann't attach sahrememory!";
    }
    QBuffer buffer;
    sharememory.lock();
    buffer.setData((char*)sharememory.constData(),sharememory.size());
    buffer.open(QBuffer::ReadWrite);
    buffer.readAll();
    sharememory.unlock();
    sharememory.detach();
    qDebug() << buffer.data().data();
}

Main.cpp文件:

#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}

3、D-Bus

    D_BUS是一種低開銷、低延遲的進程間通訊機制。Qt提供了QtDBus模塊QtDBus模塊使用D-Bus協議,把信號與槽機制(Signal and Slot)擴展到進程級別,使得開發者能夠在一個進程中發出信號,能夠再其餘進程定義槽來響應其餘進程發出的信號。

    D-Bus是一種高級的進程間通訊機制,由freedesktop.org項目提供,使用GPL許可證發行。D-Bus最主要的用途是在Linux桌面環境爲進程提供通訊,同時能將Linux桌面環境和Linux內核事件做爲消息傳遞到進程。D-Bus的主要機率爲總線,註冊後的進程可經過總線接收或傳遞消息,進程也可註冊後等待內核事件響應,例如等待網絡狀態的轉變或者計算機發出關機指令。目前,D-Bus已被大多數Linux發行版所採用,開發者可以使用D-Bus實現各類複雜的進程間通訊任務。

    D-Bus是一個消息總線系統,其功能已涵蓋進程間通訊的全部需求,並具有一些特殊的用途。D-Bus是三層架構的進程間通訊系統,其中包括:

    接口層:接口層由函數庫libdbus提供,進程可經過libdbus庫使用D-Bus的能力。

    總線層:總線層其實是由D-Bus總線守護進程提供的。在Linux系統啓動時運行,負責進程間的消息路由和傳遞,其中包括Linux內核和Linux桌面環境的消息傳遞。

    包裝層:包裝層一系列基於特定應用程序框架的Wrapper庫。

 

    在QT中的Dbus是使用的Dbus的包裝層libdbus-qt.

    要查看Dbus總線上的服務和對象能夠藉助d-feet 和qdbusviewer

    要發送信號可使用dbus-send,要查看Dbus上的消息流可使用dbus-monitor

 

4、QCOP(Qt COmmunications Protocol )

    QCOP 是 Qt 內部的一種通訊協議,這種協議用於不一樣的客戶之間在同一地址空間內部或者不一樣的進程之間的通訊。目前,這種機制還只在 Qt 的嵌入式版本中提供。

    爲實現這種通訊機制,Qt 中包括了由 QObject 類繼承而來的 QCopChannel 類,該類提供了諸如 send()、isRegistered() 等靜態函數,它們能夠在脫離對象的狀況下使用。爲了在 channel 中接收通訊數據,用戶須要構造一個 QCopChannel 的子類並提供 receive() 函數的重載函數,或者利用 connect() 函數與接收到的信號相聯繫。值得一提的是,在 Qt 系統中,只提供了 QCOP 協議機制和用於接收消息的類,而如何發送消息則沒有提供相應的類供用戶使用。

    在基於 Qt 的桌面系統 Qtopia(QPE)中,則提供了相應的發送類:QCopEnvelope。用戶能夠經過該類利用 channel 向其餘進程發送消息。該類將經過 QCopChannel 發送 QCop 消息的過程進行了封裝,用戶只須要調用該類中的相關函數就能夠方便地實現進程之間的通訊。

5、QProcess

    跨平臺類QProcess能夠用於啓動外部程序做爲子進程,並與它們進行通訊。它提供了用於監測和控制該子進程狀態的API。另外,QProcess爲從QIODevice繼承的子進程提供了輸入/輸出通道。

6、Session Management

    在Linux/X11平臺上,Qt提供了會話管理的支持。會話容許事件傳播到進程,例如,當檢測到關機時。進程和應用程序能夠執行任何須要的操做,例如:保存打開的文檔。

相關文章
相關標籤/搜索