目 錄
D-Bus是一種高級的進程間通信機制,它由freedesktop.org項目提供,使用GPL許可證發(fā)行。D-Bus最主要的用途是在Linux桌面環(huán)境為進程提供通信,同時能將Linux桌面環(huán)境和Linux內核事件作為消息傳遞到進程。D-Bus的主要概率為總線,注冊后的進程可通過總線接收或傳遞消息,進程也可注冊后等待內核事件響應,例如等待網(wǎng)絡狀態(tài)的轉變或者計算機發(fā)出關機指令。目前,D-Bus已被大多數(shù)Linux發(fā)行版所采用,開發(fā)者可使用D-Bus實現(xiàn)各種復雜的進程間通信任務。
D-Bus是一個消息總線系統(tǒng),其功能已涵蓋進程間通信的所有需求,并具備一些特殊的用途。D-Bus是三層架構的進程間通信系統(tǒng),其中包括:
接口層:接口層由函數(shù)庫libdbus提供,進程可通過該庫使用D-Bus的能力。
總線層:總線層實際上是由D-Bus總線守護進程提供的。它在Linux系統(tǒng)啟動時運行,負責進程間的消息路由和傳遞,其中包括Linux內核和Linux桌面環(huán)境的消息傳遞。
包裝層:包裝層一系列基于特定應用程序框架的Wrapper庫。
在QT中的Dbus是使用的Dbus的包裝層libdbus-qt.
要查看Dbus總線上的服務和對象可以借助d-feet 和qdbusviewer
要發(fā)送信號可以使用dbus-send,要查看Dbus上的消息流可以使用dbus-monitor
QT Dbus是在QT4.2中才引進到QT中來的,還有很多的地方不是很完善,在網(wǎng)上DBus的資料比較多,不過很多都是基入GTK的,基入QT的資料還比較的少,主要可以參考
D-Bus和QT4(wwang's blog一蓑煙雨任平生)
http://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html
其他的DBus的基本資料可以參考:
DBus學習筆記(博客園)
http://dotnet.cnblogs.com/page/76759/?page=1
愷風的CSDN博客
http://blog.csdn.net/flowingflying/archive/2009/09/07/4527634.aspx
關于QT中的DBus的用法介紹的文章比較的少,網(wǎng)上只有這篇文章(國外的網(wǎng)站上可能有更多,只是沒有發(fā)現(xiàn)而已)和QT中的四個例子程序。
這個最簡單的用法是在使用中發(fā)現(xiàn)的,不需要在Dbus的守護進程上注冊服務和注冊對象。
注冊了對象后:對象中的導出的槽就可以供其他的客戶端來調用了。
注冊了服務后:對象就有了一個公共名,沒有注冊是只有三個唯一名。
在發(fā)送端只需創(chuàng)建一個信號原后發(fā)送即可,
例如:
1) 創(chuàng)建QT的DBus信號
QDBusMessage msg=QDBusMessage::createSignal("/hotel/path", "hotel.interface", "checkIn");
2) 給信號賦值
msg<<this->ui->checkInlineEdit->text().toInt();
3) 發(fā)射信號
QDBusConnection::sessionBus().send(msg);
在接受端同樣只需要簡單的兩三步即可
1) 綁定信號
QDBusConnection::sessionBus().connect(QString(),QString(),"dbus.client.interface","Active",this,SLOT(ActiveEvent(int)));
2) 在槽中進行相關的處理
在ActiveEvent槽中執(zhí)行你的應用程序需要對這個信號做出的反應即可。
這樣的使用在DBUS的守護進程中沒有服務,只有三個唯一名,沒有公共名,也沒有任何的信號、槽、屬性。
可以通過d-feet、 qdbusviewe來查看。
可以通過dbus-monitor監(jiān)視信號發(fā)送過程
可以參考示例DBusSignalMethod中DBusServerDBusSignal和DBusClientDBusSignal
在以下這篇文章中已經(jīng)很好的介紹了QT DBus的各種常規(guī)的用法了,在此就重復了,這種用法主要是在服務端,需要在DBus的守護進程上注冊對象和注冊服務,原后其他的客戶端就可以自由的調用了。
不過這種方式也有一個好處,調用是服務端的返回的參數(shù)就只發(fā)給調用的客戶端,是一對一的,不想上面的用信號的方式,信號的方式,發(fā)送的信號是一對多的。
D-Bus和QT4 (wwang's blog一蓑煙雨任平生)
http://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html
在也有幾個小的例子程序是根據(jù)D-Bus和QT4 (wwang'sblog一蓑煙雨任平生)的例子改編的。
在常規(guī)用法中也分客戶端和服務端的,
客戶端有三種用法,服務端有兩個用法。
可以參考實例DBusMessage中的DBusServer和DBusClient
1) 創(chuàng)建一個QDBusMessage的方法調用
a) QDBusMessage m =QDBusMessage::createMethodCall("hotel.server",
i. "/hotel/path",
ii. "hotel.interface",
iii. "checkIn");
2) 給方法傳遞參數(shù)
a) m<<this->ui->checkInlineEdit->text().toInt();
3) 調用方法
a) QDBusMessage response =QDBusConnection::sessionBus().call(m);
4) 判斷方法的返回值
if (response.type()== QDBusMessage::ReplyMessage) {
// QDBusMessage的arguments不僅可以用來存儲發(fā)送的參數(shù),也用來存儲返回值;
// 這里取得checkIn的返回值
int num_room = response.arguments().takeFirst().toInt();
qDebug("Got %d %s/n", num_room, (num_room > 1) ?"rooms" : "room");
}else
{
qDebug( "Check In fail!/n");
}
可以參考實例DBusInterface中的DBusServer和DBusClientInterface
1) 創(chuàng)建一個QDBusInterface的實例
QDBusInterfaceiface( "hotel.server",
"/hotel/path",
"hotel.interface",QDBusConnection::sessionBus());
if(!iface.isValid()) {
qDebug()<< qPrintable(QDBusConnection::sessionBus().lastError().message());
exit(1);
}
2) 傳遞參數(shù)
int num_room;
num_room=this->ui->checkInlineEdit->text().toInt();
3) 呼叫遠程的checkIn,參數(shù)為num_room
QDBusReply<int>reply = iface.call("checkIn", num_room);
4) 判斷返回值
if(reply.isValid()) {
num_room = reply.value();
qDebug("Got %d %s/n", num_room, (num_room > 1) ?"rooms" : "room");
}else {
qDebug( "Check In fail!/n");
}
可以參考實例DBusProxy中的DBusClientProxy和DBusServer
DBusProxy可以使訪問更加方便,就像訪問本地類成員變量的方式訪問遠程的method
在使用這個類的時候要使用兩個工具
qdbuscpp2xml和qdbusxml2cpp
利用qdbuscpp2xml–M –S hotel.h –o hotel.xml
在利用qdbusxml2cpp hotel.xml –photelInterface
在客戶端的工程中添加這倆個文件。
1) 創(chuàng)建接口
a) hotel::interfacemyHotel("hotel.server",
a) "/hotel/path",
i. QDBusConnection::sessionBus());
2) 給參數(shù)賦值
i. int num_room;
ii. num_room=this->ui->checkInlineEdit->text().toInt();
3) 調用checkIn
a) QDBusPendingReply<int>reply = myHotel.checkIn(num_room);
4) 等待完成
a) reply.waitForFinished();
5) 判斷返回值
if (reply.isValid()) {
num_room = reply.value();
qDebug("Got %d %s/n", num_room, (num_room > 1) ?"rooms" : "room");
}else {
qDebug( "Check In fail!/n");
}
可以參考實例DBusMessage中的DBusServer
1) 創(chuàng)建連接
QDBusConnectionbus = QDBusConnection::sessionBus();
// 在session bus上注冊名為"com.test.hotel"的service
2) 注冊服務
if(!bus.registerService("hotel.server")) {
a) qDebug() <<bus.lastError().message();
b) exit(1);
}
3) 注冊對象
if(!(bus.registerObject("/hotel/path", &my_hotel , QDBusConnection::ExportAllSlots)))
{
qDebug()<< bus.lastError().message();
exit(1);
}
可以參考實例DBusAdapter中的DBusServerXML
QT4推薦使用Adapter來注冊Object。
很多情況下,我們可能只需要把我們定義的類里的方法有選擇的發(fā)布到Message Bus上,使用Adapter可以很方便的實現(xiàn)這種意圖
1) 創(chuàng)建連接
QDBusConnectionbus = QDBusConnection::sessionBus();
// 在session bus上注冊名為"com.test.hotel"的service
2) 注冊服務
if (!bus.registerService("hotel.server")) {
qDebug() << bus.lastError().message();
exit(1);
}
3) 創(chuàng)建Adaptor對象
myHotelAdaptor =new InterfaceAdaptor(&my_hotel);
4) 注冊對象
if(! (bus.registerObject("/hotel/path", &my_hotel,QDBusConnection::ExportAllSlots)))
{
qDebug() << bus.lastError().message();
exit(1);
}
在使用QT一段時間后,大家也許對QT的信號與槽很熟悉了,再來了一個DBus的信號與槽,大家可能很容易混淆了,想直接使用QT的信號與槽?
這樣也是可以的,可以參照QT的例子程序dbus-chat,中間就有這種用法的。
發(fā)射信號直接用QT的,綁定信號與槽也用QT的是不是很熟悉了。
具體的可以參考QT的實例dbus-chat
也可以參考實例QTSignalSlot中的DBusClientQTSignal和DBusServerQTSignal
發(fā)送信號端:
1 新建一個DBus服務
QDBusConnection bus =QDBusConnection::sessionBus();
2 注冊對象(注冊的時候必須注冊this,這樣this對象中的信號就可以直接發(fā)送到DBus上)
bus.registerObject("/hotel/path", this ,
QDBusConnection::ExportAllSlots|
QDBusConnection::ExportAllSignals);
接受信號端:
1 新建一個接口
myInterface= new hotel::interface(QString(),QString(),QDBusConnection::sessionBus(),this);
2 信號的綁定(注意:接收必須在DBus中注冊的對象中接收)
QObject::connect(myInterface,SIGNAL(checkIn(int)),this,SLOT(checkInSlot(int)));
注意點:
1 信號的發(fā)射端要想信號發(fā)射到DBus上去,在對象的構造函數(shù)中必須,注冊對象自己,必須使用this指針。例如:connection.registerobject(“/com/dbus/path”,this);
這樣這個類中的所有的信號都可以直接用emit發(fā)射到DBus總線上。
2 信號的接受端綁定信號是可以使用QTDBus的綁定也可以直接使用QObject的綁定。
當使用Qobject的綁定時,QObject::connect(dbusInterface,SIGNAL(testMessage),this,SLOT(testEvent);
創(chuàng)建接口時,接口的頭兩個參數(shù)必須為空,例如:
dbusInterface =newdbus::test::interface(QString(),QString(),QDBusConnection::session(),this);
綁定的信號必須是已經(jīng)導出的在interface文件有的。
當使用QDBus的綁定時,不論前兩個參數(shù)是否為空,都可以正常的接受到信號
3 只有注冊到DBus上去對象才能接受打DBus上的信號,其他的對象要接受DBus上的信號必須通過這個注冊的對象將信號轉發(fā)出來。
QObject::connect(myInterface,SIGNAL(queryReply(int)),this,SIGNAL(queryResult(int)));
聯(lián)系客服