DBus是Linux使用的程式間通訊機制,允許各個程式互相訪問,而不需要為每個其他元件實現自定義程式碼。即使對於系統管理員來說,這也是一個相當深奧的主題,但它確實有助於解釋linux的另一部分是如何工作的。
這裡主要介紹 dbus-send
與 GDbus
cli工具,其他的還有QtDbus
, d-feet
...
命令列工具dbus-send
,是freedesktoop提供的dbus包配套的命令客戶端工具,可用於傳送dbus訊息。
GDbus
GLib實現的dbus工具。較與 dbus-send
,擁有更完整的功能。
d-feet
: 可以處理所有D-Bus服務的GUI應用程式。
dbus-send
dbus有兩種訊息匯流排 (message bus
):system bus
和 session bus
,通過使用 --system
和 --session
選項來通過dbus-send
向系統匯流排或會話匯流排傳送訊息。如果兩者都未指定,預設為**session bus*.
藉此,順道聊下 system bus
和 session bus
:
-
System Bus
:- 在桌面上,為所有使用者提供一條匯流排.
- 專用於系統服務。
- 有關於低階時間,例如 網路連線,USB裝置。
- 在嵌入式Linux系統中,system bus是唯一D-Bus型別。
-
Session Bus
:- 每個使用者會話一個例項
- 為使用者應用提供那個桌面服務。
- 連線到
X-session
引數選項
--dest=NAME
: 這個是必選的引數,指定要接收訊息的介面名稱。例如 org.freedesktop.ExampleName
。
--print-reply
: 列印回覆訊息。
--print-reply=literal
: 如選項一樣,列印回覆正文。如有特殊字元,如物件或 object 則按字面列印,沒有標點符號、轉義字元等。
--reply-timeout=
: 可選引數,等待回覆的超時時長,單位為 毫秒。
--system|--session
: 傳送的訊息是system bus還是session bus,預設為 session bus.
--type=method_call|signal
: 呼叫的方法:預設為signal。
必須始終指定要傳送的訊息的物件路徑和名稱。以下引數(如果有)是訊息內容(訊息引數)。這些值作為型別指定的值給出,可能包括如下所述的容器(陣列、dict和變體)。
支援引數
dbus-send
傳送的訊息,在呼叫方法需要傳引數時,必須將這些值給出。dbus-send
支援傳入的引數的型別,並不為D-Bus支援的所有的資料型別,僅為一些簡單的型別:如
- Type: 這裡
type
僅僅為簡單的資料型別,即type:content
,支援的內容如下:string | int16 | uint16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
。 - 陣列:
array = array:<type>:<value>[,<value>...]
- 詞典:
dict = dict:<type>:<type>:<key>,<value>[,<key>,<value>...]
。 - 變體:
variant = variant:<type>:<value>
。
根據官網的解析出來後如上述集中資料型別,更詳細的描述可以根據官方 dbus-send 進行參考。
可以通過一張圖來理解 dbus-send
傳送一個訊息所需的幾個必須引數
通過簡單的命令,來了解一個 dbus-send
命令如何傳入引數
dbus-send --dest=org.freedesktop.ExampleName \ # service
/org/freedesktop/sample/object/name \ # object
org.freedesktop.ExampleInterface.ExampleMethod \ # interface.method
int32:47 string:'hello world' double:65.32 \ # param int
array:string:"1st item","next item","last item" \ # param array
dict:string:int32:"one",1,"two",2,"three",3 \ # param dict
variant:int32:-8 \ # param variant
objpath:/org/freedesktop/sample/object/name # param object_path
使用案例
如列出所有匯流排介面
dbus-send --session \
--dest=org.freedesktop.DBus \
--type=method_call \
--print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListNames
檢視對方匯流排所支援的物件介面,org.freedesktop.DBus.Introspectable
、org.freedesktop.DBus.Properties
和 org.freedesktop.PowerManagement
。每個介面實現一些方法和訊號。這些是你可以與之互動的東西。
dbus-send --session \
--type=method_call \
--print-reply \
--dest=org.freedesktop.DBus \
/ \
org.freedesktop.DBus.Introspectable.Introspect
dbus-send
,也支援呼叫遠端匯流排介面,通過預設通過 DBUS_SESSION_BUS_ADDRESS
或 DBUS_SYSTEM_BUS_ADDRESS
,來指定遠端的匯流排。
DBUS_SESSION_BUS_ADDRESS=""
dbus-send --session \
--type=method_call \
--print-reply \
--dest=org.freedesktop.DBus \
/ \
org.freedesktop.DBus.Introspectable.Introspect
gdbus
gdbus是 GLib實現的dbus工具。較與 dbus-send
,擁有更完整的功能。
introspect
: 可以列印出物件的介面和屬性值。對應物件的所有者需要實現org.freedesktop.DBus.Introspectable
的介面。使用 --xml
選項,將列印返回的xml
格式。--recurse
選項可將其子級等列印,--only
選項僅列印具有屬性的介面。
monitor
: 類似於 dbus-monitor
call
: 呼叫一個方法,傳入的必須為 GVariant
,而相應的也為GVariant
。
emit
: 發出訊號。訊號中包含的每個引數除字串外都必須序列化為GVariant。
使用案例
gdbus introspect --system \
--dest org.freedesktop.UPower \
--object-path \
/ \
--recurse \
--only-properties
通過call 來向一個dbus service傳送資訊
gdbus call --session \
--dest org.freedesktop.Notifications \
--object-path /org/freedesktop/Notifications \
--method org.freedesktop.Notifications.Notify \
my_app_name \
42 \
gtk-dialog-info \
"The Summary" \
"Here's the body of the notification" \
[] \
{} \
5000
(uint32 12,)
監聽一個服務的物件
gdbus monitor \
--system \
--dest org.freedesktop.NetworkManager \
--object-path /org/freedesktop/NetworkManager/AccessPoint/4141
傳送訊號
gdbus emit --session \
--object-path /foo \
--signal org.bar.Foo "['foo', 'bar', 'baz']"
想特定程式傳送訊號,`--dest 為指定程式。
gdbus emit \
--session \
--object-path /bar \
--signal org.bar.Bar someString \
--dest :1.42