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