D-Bus 完整教程 / 03 - D-Bus 基本工具
第 03 章:D-Bus 基本工具
3.1 工具概览
D-Bus 生态提供了丰富的命令行和图形工具:
| 工具 | 来源 | 类型 | 特点 |
|---|---|---|---|
dbus-send | dbus 包 | 命令行 | 发送单条消息,最基础 |
dbus-monitor | dbus 包 | 命令行 | 监听总线上的消息流 |
busctl | systemd | 命令行 | 功能最全面,推荐日常使用 |
gdbus | GLib / GIO | 命令行 | 支持代码生成 |
d-feet | GNOME | 图形 | 可视化浏览,适合学习 |
bustle | Haskell | 图形 | 消息时序图分析 |
qdbus | Qt | 命令行 | Qt 环境下的工具 |
3.2 busctl — 推荐的日常工具
busctl 是 systemd 提供的 D-Bus 工具,功能全面,输出格式友好。
3.2.1 列出所有总线名称
# 列出 System Bus 上的服务
busctl list
# 列出 Session Bus 上的服务
busctl --user list
# 输出示例:
# NAME PID PROCESS USER CONNECTION UNIT
# org.freedesktop.DBus - - - - -
# :1.0 1 systemd root systemd init.scope
# :1.42 1234 gnome-shell user - -
# org.freedesktop.NetworkManager 567 NetworkManager root - NetworkManager.service
3.2.2 查看服务详情
# 查看服务的接口列表
busctl tree org.freedesktop.login1
# 输出示例:
# /org/freedesktop/login1
# ├─/org/freedesktop/login1/seat
# │ └─/org/freedesktop/login1/seat/seat0
# ├─/org/freedesktop/login1/session
# │ ├─/org/freedesktop/login1/session/c1
# │ └─/org/freedesktop/login1/session/c2
# └─/org/freedesktop/login1/user
# └─/org/freedesktop/login1/user/_1000
3.2.3 查看接口详情
# 查看某个对象的所有接口、方法、属性、信号
busctl introspect org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager
# 输出示例:
# NAME TYPE SIGNATURE RESULT/VALUE FLAGS
# .CanHibernate method - s -
# .CanHybridSleep property s "yes" emits-change
# .Kill method sis - -
# .LockSession method s - -
# .PrepareForShutdown signal b - -
# .PreparingForShutdown signal b - -
3.2.4 调用方法
# 调用 systemd-logind 的 CanHibernate
busctl call \
org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager \
CanHibernate
# 输出:s "yes"
# 调用带参数的方法(获取用户列表)
busctl call \
org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager \
ListUsers
3.2.5 获取/设置属性
# 获取单个属性
busctl get-property \
org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager \
BlockInhibited
# 获取所有属性
busctl get-property \
org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager \
--all
# 设置属性(如果接口允许)
busctl set-property \
org.example.SomeService \
/org/example/Object \
org.example.Interface \
SomeProperty \
s "new value"
3.2.6 监控消息
# 监控所有消息
busctl monitor --user
# 只监控特定服务的消息
busctl monitor --user org.freedesktop.portal.Desktop
# 使用匹配规则过滤
busctl monitor --user \
--match="type='signal',interface='org.freedesktop.DBus.Properties'"
3.2.7 查看总线状态
# 查看总线统计信息
busctl status
# 输出示例:
# BusName=org.freedesktop.systemd1
# BusId=...
# SenderName=:1.0
# ConnectedSince=...
# Eavesread=false
# ...
3.3 dbus-send — 基础消息发送
dbus-send 是最原始的 D-Bus 命令行工具,适合发送单条消息。
3.3.1 基本语法
dbus-send [--system | --session] \
--dest=<bus_name> \
--type=<method_call|signal> \
--print-reply \
<object_path> \
<interface>.<method> \
[参数...]
3.3.2 方法调用
# 无参数调用
dbus-send --session --dest=org.freedesktop.DBus \
--type=method_call --print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListNames
# 带参数调用(字符串)
dbus-send --session --dest=org.freedesktop.DBus \
--type=method_call --print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.NameHasOwner \
string:"org.freedesktop.DBus"
# 多种类型参数
dbus-send --session --dest=org.example.Service \
--type=method_call --print-reply \
/org/example/Object \
org.example.Interface.Method \
int32:42 \
string:"hello" \
double:3.14 \
boolean:true \
array:string:"a","b","c" \
dict:string:int32:"key",100
3.3.3 参数类型对照表
| D-Bus 类型 | dbus-send 语法 | 示例 |
|---|---|---|
| BYTE | byte: | byte:255 |
| BOOLEAN | boolean: | boolean:true |
| INT16 | int16: | int16:-100 |
| UINT16 | uint16: | uint16:65535 |
| INT32 | int32: | int32:-100000 |
| UINT32 | uint32: | uint32:100000 |
| INT64 | int64: | int64:-99999 |
| UINT64 | uint64: | uint64:99999 |
| DOUBLE | double: | double:3.14 |
| STRING | string: | string:"hello" |
| OBJECT_PATH | objpath: | objpath:"/org/example" |
| SIGNATURE | signature: | signature:"si" |
| ARRAY | array: | array:int32:1,2,3 |
| VARIANT | variant: | variant:string:"hello" |
| DICT_ENTRY | dict: | dict:string:int32:"k",1 |
3.3.4 发送信号
# 发送一条自定义信号
dbus-send --session \
--type=signal \
/org/example/Test \
org.example.Test.SomethingHappened \
string:"hello from dbus-send"
在另一个终端监听:
busctl monitor --user --match="type='signal'"
3.4 dbus-monitor — 消息监听
# 监听 Session Bus(不显示系统消息)
dbus-monitor --session
# 监听 System Bus(需要权限)
dbus-monitor --system
# 只监听信号
dbus-monitor --session "type='signal'"
# 只监听特定接口
dbus-monitor "interface='org.freedesktop.DBus.Properties'"
# 监视特定服务
dbus-monitor --session "destination=':1.42'"
输出格式:
method call time=1234567890.123456 sender=:1.42 -> dest=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=ListNames
method return time=1234567890.123789 sender=:1.0 -> dest=:1.42 serial=2 reply_serial=1
array [
string "org.freedesktop.DBus"
string ":1.0"
string ":1.42"
]
注意:
dbus-monitor无法以 eavesdrop 模式监听系统总线上的所有消息(需要特权)。busctl monitor在 systemd 环境下表现更好。
3.5 gdbus — GLib 附带的工具
# 列出总线上的名称
gdbus introspect --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus
# 调用方法
gdbus call --session \
--dest org.freedesktop.DBus \
--object-path /org/freedesktop/DBus \
--method org.freedesktop.DBus.ListNames
# 监视信号
gdbus monitor --session --dest org.freedesktop.DBus
# 查看属性
gdbus call --session \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.DBus.Properties.GetAll \
"org.freedesktop.login1.Manager"
gdbus 的独特优势是支持 代码生成:
# 从 XML 接口描述生成 C 代码骨架
gdbus-codegen \
--generate-c-code my-service \
--c-namespace MyApp \
--interface-prefix org.example \
org.example.MyService.xml
3.6 d-feet — 图形化浏览器
d-feet 是 GNOME 的 D-Bus 图形调试工具,适合初学者学习。
# 启动 d-feet
d-feet &
功能:
- 左侧树形显示所有总线名称
- 点击名称展开对象路径树
- 查看接口的方法、属性、信号
- 直接在 GUI 中调用方法并查看返回值
- 实时查看属性值
替代方案:如果在 Wayland 或无桌面环境下,可以使用
busctl的交互功能,或者安装d-spy(GNOME 45+ 推荐的 D-Bus 浏览器)。
3.7 bustle — 消息时序分析
bustle 是一个可以录制和分析 D-Bus 消息时序的图形工具。
# 安装
sudo apt install bustle # Debian/Ubuntu
sudo dnf install bustle # Fedora
# 录制 Session Bus 消息
bustle --session
# 录制 System Bus 消息(需要 root)
sudo bustle --system
录制结束后,bustle 会生成消息时序图:
时间轴 ↓
│
App A ├──MethodCall──→│ │──→ MethodReturn
│ │ dbus- │
App B │──Signal──────→│ daemon │──→ Signal 到所有订阅者
│ │ │
App C │ │←─MethodCall│
│ │ │──→ MethodReturn
3.8 实战演练:查询系统信息
演练 1:查询系统主机名
# 方法 1:使用 busctl
busctl call \
org.freedesktop.hostname1 \
/org/freedesktop/hostname1 \
org.freedesktop.DBus.Properties \
GetAll \
s "org.freedesktop.hostname1"
# 方法 2:使用 gdbus
gdbus call --system \
--dest org.freedesktop.hostname1 \
--object-path /org/freedesktop/hostname1 \
--method org.freedesktop.DBus.Properties.GetAll \
"org.freedesktop.hostname1"
# 方法 3:使用 dbus-send
dbus-send --system --dest=org.freedesktop.hostname1 \
--type=method_call --print-reply \
/org/freedesktop/hostname1 \
org.freedesktop.DBus.Properties.GetAll \
string:"org.freedesktop.hostname1"
演练 2:查询蓝牙设备列表
# 查看 BlueZ 的对象树
busctl tree org.bluez
# 获取默认适配器
busctl call \
org.bluez \
/ \
org.freedesktop.DBus.ObjectManager \
GetManagedObjects
演练 3:锁屏与休眠
# 锁屏(GNOME)
busctl call \
org.gnome.ScreenSaver \
/org/gnome/ScreenSaver \
org.gnome.ScreenSaver \
Lock
# 查询是否可休眠
busctl call \
org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager \
CanHibernate
# 休眠(需要授权)
busctl call \
org.freedesktop.login1 \
/org/freedesktop/login1 \
org.freedesktop.login1.Manager \
Hibernate \
b true
演练 4:监控属性变化
# 终端 1:监控 PropertiesChanged 信号
busctl monitor --user \
--match="type='signal',member='PropertiesChanged'"
# 终端 2:改变音量(触发属性变化)
busctl call \
org.pulseaudio.Server \
/org/pulseaudio/server1 \
org.pulseaudio.Server \
SetSinkVolume \
u 0 \
t 50000
3.9 工具对比速查表
| 功能 | busctl | dbus-send | dbus-monitor | gdbus | d-feet |
|---|---|---|---|---|---|
| 列出名称 | ✅ | ❌ | ❌ | ✅ | ✅ |
| 树形浏览 | ✅ | ❌ | ❌ | ✅ | ✅ |
| 内省 | ✅ | ❌ | ❌ | ✅ | ✅ |
| 调用方法 | ✅ | ✅ | ❌ | ✅ | ✅ |
| 获取属性 | ✅ | ✅ | ❌ | ✅ | ✅ |
| 设置属性 | ✅ | ❌ | ❌ | ❌ | ✅ |
| 监听消息 | ✅ | ❌ | ✅ | ✅ | ❌ |
| 匹配规则 | ✅ | ❌ | ✅ | ✅ | ❌ |
| 代码生成 | ❌ | ❌ | ❌ | ✅ | ❌ |
| 图形界面 | ❌ | ❌ | ❌ | ❌ | ✅ |
本章小结
| 工具 | 最佳用途 |
|---|---|
busctl | 日常交互首选,功能最全面 |
dbus-send | 发送单条消息,脚本中使用 |
dbus-monitor | 监听原始消息流 |
gdbus | GLib 环境下的调试,代码生成 |
d-feet / d-spy | 图形化浏览 D-Bus 对象 |