1. 程式人生 > >QT開發(三十五)——QT程序間通訊

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

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

    Qt 是一個跨平臺的應用框架,其程序間通訊機制當然可以使用所在平臺的程序間通訊機制,如在Windows平臺上的Message機制、共享記憶體、檔案對映、管道、Socket等。其中,Qt對一些許多平臺共有的IPC機制進行了封裝。

一、TCP/IP

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

二、QShared Memory(共享記憶體)

    Qt提供的基於共享記憶體的IPC有QSharedMemory類和QSystemSemaphore類,QSharedMemory可以訪問共享記憶體區域,以及多執行緒和程序的共享記憶體區域,而

QSystemSemaphore類用於訪問系統共享資源,以實現獨立程序間的通訊。

1、QSharedMemory

    QSharedMemory讀寫記憶體時,可以使用lock()實現同步。如果同步完成,必須使用unlock()為共享記憶體區域解鎖。

    QSharedMemory可以使用attach()訪問共享記憶體,通過指定引數來設定共享記憶體的訪問模式。如果使用的是QSharedMemory::ReadOnly模式,則只能通過只讀模式訪問共享記憶體,如果使用QSharedMemory::ReadWrite模式則可以通過讀寫模式訪問共享記憶體。

    QSharedMemory擁有程序並提供可以返回共享記憶體區域指標的成員函式。在共享記憶體區域,成員函式constData()可以通過void 型別返回程序正在使用的記憶體區域指標。建立共享時,QSharedMemory可以以位元組為單位分配共享記憶體區域,還可以通過第二個引數設定函式 attach()提供的模式。

    QSharedMemory可以設定特定共享記憶體的固定鍵。函式setNativeKey()可以設定共享記憶體物件的鍵,setNativeKey()函式使用從屬平臺的共享記憶體的鍵進行相關設定。使用函式setKey()可以設定獨立於平臺的鍵。函式setKey()建立與平臺本地鍵(Native Key)對映的鍵。

    初始化QSharedMemory時,必須指定一個唯一的標識Key,程序的Key必須保持一致。可以使用setKey來設定。

2、QSystemSemaphore

    QSystemSemaphore可以提供普通系統的訊號量。訊號量使用互斥體,而互斥體只可以使用1次鎖定(Block)。因此,QSemaphore類不能對有效資源使用多執行緒,而QSystemSemaphore類可以再多程序或多執行緒中實現。

    QSystemSemaphore與QSemaphore類不同,可以訪問多程序。這表示QSystemSemaphore是一個重量級的類。因 此,使用單一執行緒或程序時,建議使用QSemaphore。獲得資源前,成員函式acquire()始終阻塞。函式release()用於釋放資源,且該 函式可以設定引數。該函式的引數>1時,釋放資源。

3、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()

4、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();}

三、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

四、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 訊息的過程進行了封裝,使用者只需要呼叫該類中的相關函式就可以方便地實現程序之間的通訊。

五、QProcess

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

六、Session Management

    在Linux/X11平臺上,Qt提供了會話管理的支援。會話允許事件傳播到程序,例如,當檢測到關機時。程序和應用程式可以執行任何必要的操作,例如:儲存開啟的文件。

本文出自 “生命不息,奮鬥不止” 部落格,謝絕轉載!