天天看點

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提供了會話管理的支援。會話允許事件傳播到程序,例如,當檢測到關機時。程序和應用程式可以執行任何必要的操作,例如:儲存打開的文檔。

【領QT開發教程學習資料,點選下方連結莬費領取↓↓,先碼住不迷路~】

「連結」

繼續閱讀