DBUS及常用介面介紹
如圖 2‑1所示,程序1(Process1)需先連線到匯流排(dbus_bus_get),其次構造訊息(dbus_message_new_signal),然後傳送訊息(dbus_connection_send)到後臺程序。後臺程序接收訊息,然後根據訊息型別對訊息進行不同處理(bus_dispatch_matches)。
程序2(Process2)接收訊息前需要連線到匯流排,並告知匯流排自己希望得到的訊息型別(dbus_bus_add_match),然後等待接收訊息(dbus_connection_pop_message)。程序2(Process2)收到匯流排轉發的訊息時會根據訊息型別,做不同的處理(若是訊號型別則不需要傳送返回值給匯流排)。
2.2 連線到匯流排
程序間通訊前,需要連線到匯流排。呼叫dbus_bus_get函式連線程序到匯流排,建立程序和匯流排之間的連線(DBusConnection)。建立連線後,需要為這個連線註冊名稱,方便後面對這個連線進行操作,呼叫dbus_bus_request_name函式對連線進行註冊名稱。
建立連線和註冊名稱是在程式開始時執行,程式結束時,呼叫dbus_connection_close函式關閉一個連線。函式介面宣告如程式清單 2‑1所示。
程式清單 2-1 建立、註冊名稱和關閉連線
DBusConnection *dbus_bus_get (DBusBusType type, DBusError *error) /* 建立和匯流排的連線 */ int dbus_bus_request_name (DBusConnection *connection, const char *name, unsigned int flags, DBusError *error) /* 註冊連線名稱 */ void dbus_connection_close (DBusConnection *connection) /* 關閉連線 */
2.3 訊號傳送與接收
2.3.1 訊號傳送
DBUS中訊號是一種廣播的訊息,當發出一個訊號,所有連線到 DBUS 總線上並註冊了接受對應訊號的程序,都會收到該訊號。
程序發出一個訊號前,需要建立一個 DBusMessage 物件來代表訊號,然後追加上一些需要發出的引數,就可以發向匯流排了。發完之後需要釋放訊息物件。訊號傳送的函式宣告如程式清單 2‑2所示。 程式清單2-2 訊號傳送介面DBusMessage *dbus_message_new_signal (const char *path, const char *iface, const char *name) /* 建立訊號型別訊息 */ void dbus_message_iter_init_append ( DBusMessage *message, DBusMessageIter *iter) /* 加入引數到訊號 */ dbus_bool_t dbus_connection_send ( DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial) /* 傳送訊號到匯流排 */ void dbus_message_unref (DBusMessage *message) /* 釋放訊息 */
2.3.2 訊號接收
程序接收訊號時,需先告知匯流排程序感興趣的訊息,然後等待接收訊息。訊號接收函式宣告如程式清單 2‑3所示。程式清單 2-3 訊號接收介面
void dbus_bus_add_match ( DBusConnection *connection,
const char *rule,
DBusError *error) /* 告知匯流排感興趣的訊息 */
DBusMessage *dbus_connection_pop_message ( DBusConnection *connection) /* 接收訊息 */
dbus_bool_t dbus_message_is_signal (DBusMessage *message,
const char *iface,
const char *signal_name) /* 判斷訊息是否為訊號 */
2.4 函式呼叫和提供函式呼叫
2.4.1 函式呼叫
呼叫一個遠端函式與傳送一個訊號原理類似,需要先建立一個訊息(DBusMessage),然後通過註冊在 DBUS上的名稱指定傳送的物件。然後追加相應的引數,呼叫方法分為兩種,一種是阻塞式的,另一種為非同步呼叫。非同步呼叫的時候會得到一個“DBusMessage *” 型別的返回訊息,從這個返回訊息中可以獲取一些返回的引數。
函式呼叫的函式宣告如程式清單 2‑4所示。 程式清單 2-4 函式呼叫介面DBusMessage *dbus_message_new_method_call (const char *destination,
const char *path,
const char *iface,
const char *method) /* 建立一個函式呼叫訊息 */
void dbus_message_iter_init_append (DBusMessage *message,
DBusMessageIter *iter) /* 為訊息新增引數 */
dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection,
DBusMessage *message,
DBusPendingCall **pending_return,
int timeout_milliseconds) /* 傳送訊息 */
void dbus_pending_call_block (DBusPendingCall *pending) /* 阻塞等待返回值 */
DBusMessage *dbus_pending_call_steal_reply (DBusPendingCall *pending) /* 獲得返回訊息 */
dbus_bool_t dbus_message_iter_init (DBusMessage *message,
DBusMessageIter *iter) /* 獲取引數 */
2.4.2 接收函式呼叫
提供遠端函式呼叫,首先需告知匯流排程序感興趣的訊息,其次從匯流排獲取訊息並判定訊息是方法呼叫。然後從訊息中獲取引數進行函式執行,最後建立返回訊息,併發送訊息至匯流排,由匯流排轉發至呼叫的程序。函式宣告如程式清單 2‑5所示。 程式清單 2-5 接收函式呼叫介面void dbus_bus_add_match ( DBusConnection *connection,
const char *rule,
DBusError *error) /* 請求獲取呼叫訊息 */
DBusMessage *dbus_connection_pop_message ( DBusConnection *connection) /* 從匯流排獲取訊息 */
dbus_bool_t dbus_message_is_method_call (DBusMessage *message,
const char *iface,
const char *method) /* 判定訊息是方法呼叫 */
dbus_bool_t dbus_message_iter_init (DBusMessage *message,
DBusMessageIter *iter) /* 獲取引數 */
DBusMessage *dbus_message_new_method_return (DBusMessage *method_call) /* 建立返回訊息 */
void dbus_message_iter_init_append ( DBusMessage *message,
DBusMessageIter *iter) /* 在訊息中填入引數 */
dbus_bool_t dbus_connection_send ( DBusConnection *connection,
DBusMessage *message,
dbus_uint32_t *serial) /* 傳送返回訊息 */
3. 小結
DBUS是一種高效、易用的程序間通訊方式。本文件介紹了DBUS的通訊原理,以訊號收發和方法呼叫為框架,介紹了DBUS中常用的函式介面。