D-Bus三層架構
D-Bus是一個為應用程序間通信的消息總線系統, 用於進程之間的通信。它是個3層架構的IPC 系統,包括:
1、函數庫libdbus ,用於兩個應用程序互相聯系和交互消息。
2、一個基於libdbus構造的消息總線守護進程,可同時與多個應用程序相連,並能把來自一個應用程序的消息路由到0或者多個其他程序。
3、基於特定應用程序框架的封裝庫或捆綁(wrapper libraries or bindings )。例如,libdbus-glib和libdbus-qt,還有綁定在其他語言,例如Python的。大多數開發者都是使用這些封裝庫的API,因為它們簡化了D-Bus編程細節。libdbus被有意設計成為更高層次綁定的底層后端(low-levelbackend )。大部分libdbus的 API僅僅是為了用來實現綁定。
D-Bus進程通信簡單框架
DBUS中消息分為四類:
1. Methodcall消息:將觸發一個函數調用 ;
2. Methodreturn消息:觸發函數調用返回的結果;
3. Error消息:觸發的函數調用返回一個異常 ;
4. Signal消息:通知,可以看作為事件消息。
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) /* 發送返回消息 */
參考資料:
http://blog.csdn.net/eastmoon502136/article/details/10044993
https://blog.csdn.net/mr_wangning/article/details/60324291
https://www.cnblogs.com/liyiwen/archive/2012/12/02/2798876.html