Page MenuHomePhabricator

D-Bus
Updated 1,298 Days AgoPublic

D-Bus 是 (desktop) component 之間的 RPC (IPC) 機制。它提供了一個中央控管的 bus 架構,避免 component 之間為了溝通,需要一對一建立管道。

UNIX 桌面系統中,通常會有兩個這樣的 bus,一個是全系統的 system bus,另一個則是 user login 後建立的 session bus。

每支程式連上 bus,就會取得一個唯一的連線名稱(unique connection name),這個名稱是用來識別這個連線,每次斷線重連都會不同。通常會長的像這樣 :1.1553, 它有一個固定的 prefix 也就是冒號(:),之後的代號則沒有定義。另外程式可以要求擁有額外的連線名稱(bus name),例如說 org.freedesktop.NetworkManager,通常是作為一種服務的識別(例如網路連線服務、時間服務),用來給其他元件 discover 用,因此也稱為 well-known bus name。

D-Bus 並沒有定義 transport 層,也就是說可以透過 UNIX socket、TCP/IP、甚至 message broker 來實做。不過目前 UNIX desktop 大多使用 reference implementation,也就是 dbus-daemon,通常都是以 UNIX socket(?, or netlink?) 來提供服務。

真正的服務是以 object 的方式 export 出來,object 會有一個以上的 interface 來描述服務的內容,每個 interface 則可以包含 method (request-response)和 signal (event pub-sub)。object 通常是以類似路徑(object path)的方式來命名,例如 /org/kde/kspread/sheets/3/cells/4/5,路徑名稱在一個連線中必須是唯一。因此一個 object 的完整識別碼是 bus name 加上 object path。

每個 bus 都有一個特殊的 object 用來做管理的用途。該 object 的 bus name 是 org.freedesktop.DBus,object path 是 /org/freedesktop/DBus,實作的 interface 則是 org.freedesktop.DBus。其他 component 可以對它查詢 bus 狀態、訂閱 well-known bus name 的 event 等等。

使用 object 服務的第一種方式是 request-response,object 是以 interface 中的 method 來描述。使用 method 之後不是從提供服務的 object 得到結果,就是得到一個表示發生錯誤的 response。

使用 object 服務的第二種方式是 publish-subscribe,object 是以 interface 中的 signal 來描述。訂閱 signal 的管理是 bus 的責任,object 只負責丟出 signal,由 bus 負責 deliver 給訂閱的連線。

D-Bus 定義了訊息的內容,包含 request-response 和 publish-subscribe 的訊息格式、以及 method 和 signal 中使用的資料型別。

用 org.freedesktop.DBus.Introspectable interface 中的 Introspect method 可以查詢某 object export 的
interfaces,輸出格式是 XML,例如用 libdbus 的 dbus-send:

iongchun@newage:~$ dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Introspectable.Introspect
method return time=1494641297.521827 sender=org.freedesktop.DBus -> destination=:1.25632 serial=3 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="org.freedesktop.DBus">
    <method name="Hello">
      <arg direction="out" type="s"/>
    </method>
...
    <signal name="NameOwnerChanged">
      <arg type="s"/>
      <arg type="s"/>
      <arg type="s"/>
    </signal>
...
</node>
"

或是用 gdbus,輸出為類似 Java 語法:

iongchun@newage:~$ gdbus introspect --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus
node /org/freedesktop/DBus {
  interface org.freedesktop.DBus {
    methods:
      Hello(out s arg_0);
...
    signals:
      NameOwnerChanged(s arg_0,
                       s arg_1,
                       s arg_2);
...
};
Last Author
iongchun
Last Edited
May 13 2017, 9:56 PM

Event Timeline

iongchun moved this document from D-Bus.May 13 2017, 9:56 PM