强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

D-Bus 完整教程 / 03 - D-Bus 基本工具

第 03 章:D-Bus 基本工具


3.1 工具概览

D-Bus 生态提供了丰富的命令行和图形工具:

工具来源类型特点
dbus-senddbus 包命令行发送单条消息,最基础
dbus-monitordbus 包命令行监听总线上的消息流
busctlsystemd命令行功能最全面,推荐日常使用
gdbusGLib / GIO命令行支持代码生成
d-feetGNOME图形可视化浏览,适合学习
bustleHaskell图形消息时序图分析
qdbusQt命令行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 语法示例
BYTEbyte:byte:255
BOOLEANboolean:boolean:true
INT16int16:int16:-100
UINT16uint16:uint16:65535
INT32int32:int32:-100000
UINT32uint32:uint32:100000
INT64int64:int64:-99999
UINT64uint64:uint64:99999
DOUBLEdouble:double:3.14
STRINGstring:string:"hello"
OBJECT_PATHobjpath:objpath:"/org/example"
SIGNATUREsignature:signature:"si"
ARRAYarray:array:int32:1,2,3
VARIANTvariant:variant:string:"hello"
DICT_ENTRYdict: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 工具对比速查表

功能busctldbus-senddbus-monitorgdbusd-feet
列出名称
树形浏览
内省
调用方法
获取属性
设置属性
监听消息
匹配规则
代码生成
图形界面

本章小结

工具最佳用途
busctl日常交互首选,功能最全面
dbus-send发送单条消息,脚本中使用
dbus-monitor监听原始消息流
gdbusGLib 环境下的调试,代码生成
d-feet / d-spy图形化浏览 D-Bus 对象

扩展阅读