上次討論過在OpenWrt之中的IPC服務ubus,所以這次要來探討更大的系統Ubuntu之中所使用的IPC,也就是D-Bus。關於ubus的使用,有興趣可以參考這篇。
從D-Bus的Wiki可以看到洋洋灑灑的介紹,但是這裡想要討論的是關於D-Bus的各種Implementations。目前比較常看到的有libdbus、sd-bus和GDBus等等,大體而言這三個都有依照D-Bus的標準來實作,只是三者在函式實作的等級不一樣。
libdbus可以算是最低階的API,但也因為低階,所以使用上就得自己處理很多細節。GDBus算是最高階的,可以省掉很多設定。但是這次主要想探討的事sd-bus,因為根據網路上的資料,這應該是幾個D-Bus實作之中,速度最快的。有興趣可以參考這篇資料。再者,網路上能夠參考資料並不多,所以就嘗試把自己測試過的結果給記錄下來。
sd-bus最常看到的參考資料是這個網站。對於一些概念跟測試方法、範例都寫得很詳盡。
sd-bus之中比較重要的概念有兩個:
1. method: 用以呼叫執行及回傳結果
2. signal: 用以通知其他程序,對於自身狀態的改變或者其他資料等等
所以在架構上,method會長這樣
從demoA呼叫demoB的method,並且demoB做完之後,把結果回傳給demoA。
而signal則是
demoB如果有什麼更新資料,可以透過signal送給D-Bus;而demoA本身透過sd_bus_add_match()這個函式,可以獲取相符合的signal資料。
所以兩個程式在實作的概念上,有幾個步驟要做
連結到session Bus,system Bus通常都還要配合權限的設定,權限的檔案可以參考/etc/dbus-1/system.d/底下的檔案。
r = sd_bus_open_user(&manager->bus);
加入整個物件的內容,包含methods, signals r = sd_bus_add_object_vtable(
manager->bus,
&manager->slot,
OBJECT_PATH, /* object path */
INTERFACE_NAME, /* interface name */
service_vtable,
NULL);
加入所要獲取的signals r = sd_bus_add_match(
manager->bus,
NULL,
"type='signal',"
"sender='com.cybernut.demoB',"
"interface='com.cybernut.demoB.ServiceB',"
"member='SignalTestB',"
"path='/com/cybernut/demoB/ServiceB'",
match_signal_test,
NULL);
呼叫method r = sd_bus_call_method(
manager->bus,
"com.cybernut.demoA",
"/com/cybernut/demoA/ServiceA",
"com.cybernut.demoA.ServiceA",
"Multiply",
&error,
&m_fr_demoA,
"xx",
x,
y);
送出signal r = sd_bus_emit_signal(
manager->bus,
OBJECT_PATH, /* object path */
INTERFACE_NAME, /* interface name */
"SignalTestB",
"x", test_message);
好用的小工具: D-Feet
打開D-Feet,選擇session Bus,然後輸入service names。可以找到自己寫的程式。
並且可以看到各個介面,包含methods和signals。
執行結果
持續收到demoB的signals。
每隔5秒,送出signal給demoA。
另外一個demo case:
從D-Feet去呼叫DemoB的method,接著由demoB呼叫demoA的method;在執行完之後,由demoA回傳結果給demoB,再由demoB回傳給D-Feet。
整包程式碼,參考GitHub。
沒有留言:
張貼留言