1. 概述
D-Bus 是 Linux 上的一种进程间通信方式,内部使用 socket 技术实现。是 freedesktop.org 专案的一部分,其设计目的是使Linux桌面环境(如GNOME与KDE等)提供的服务标准化。
应用程序可以在总线上注册 D-Bus 服务,对其他程序提供函数接口服务和信号通知。 客户端可以调用服务的接口和绑定服务的信号通知。
D-Bus 有两条总线,分别是 system bus 和 session bus。
- system bus: 系统总线。顾名思义,通常被系统框架使用。和常规应用分来是为了避免消息拥塞造成延迟或卡顿。
- session bus: 会话总线。常规应用使用。
D-Bus 提供两个命令工具,使用 dbus-send 命令发送消息可以调用 dbus 服务的方法,使用 dbus-monitor 命令可以监控 dbus 服务发出的信号。
借助这两个命令我们可以对创建的 dbus 服务进行接口测试,而不必编码测试接口功能是否符合预期。
2. 命令 dbus-send 详解
dbus-send 命令其本质是将消息发送到指定的总线上去,总线再分发到对应的服务触发接口调用。官方链接:DBUS-send。命令的全参数如下:
dbus-send [ --system | --session | --bus=ADDRESS | --peer=ADDRESS ] [--sender=NAME] [--dest=NAME] [ --print-reply [=literal]] [--reply-timeout=MSEC] [--type=TYPE] OBJECT_PATH INTERFACE.MEMBER [CONTENTS...]
参数 | 说明 |
---|---|
[ --system | --session | --bus=ADDRESS | --peer=ADDRESS ] | –system 系统总线 –session 会话总线(默认) –address ADDRESS:监视在ADDRESS处给定的任意消息总线 –peer=ADDRESS:端口 |
[–sender=NAME] | 指定发送者名称,告诉接受者消息来源。不指定会被默认为用户名或进程名。通常无需指定。 |
[–dest=NAME] | 必选的参数,dbus 服务名称 ,如: com.myos.conf |
[ --print-reply [=literal]] | –print-reply:打印回复消息,也带代表着–type=method_call。 –print-reply=literal:打印发送的消息的回复,并打印回复的正文。如果回复是对象路径或字符串,则按字面意思打印,不带标点符号、转义字符等。 |
[–reply-timeout=MSEC] | 等待回复的超时时长,单位为 毫秒。默认25秒超时。 |
[–type=TYPE] | method_call:方法调用 signal:信号(默认) |
OBJECT_PATH INTERFACE.MEMBER [CONTENTS…] | 依次填写对象路径、接口名.方法名、参数(可多个)。均以空格隔开。 |
有些方法需要传递参数,也就是上表中数组 [CONTENTS…] 的内容。参数之间空格隔开即可。如:
dbus-send --system --print-reply=literal --dest=com.myos.conf /conf com.myos.conf.setValue string:"language" string:"zh_CN"
dbus-send 支持的参数类型完整列表如下:
参数 | 说明 | 示例 |
---|---|---|
: | 基本类型参数,type取值: string int16 uint16 int32 uint32 int64 uint64 double byte boolean objpath | int32:47 string:‘hello world’ double:65.32 objpath:/org/freedesktop/sample/object/name |
array::[,…] | 数组参数 | array:string:“1st item”,“next item”,“last item” |
dict:::,[,,…][,…] | 字典参数 | dict:string:int32:“one”,1,“two”,2,“three”,3 |
variant:: | 变体参数 | variant:string:“zhangsan” variant:int32:-8 |
2.1 查看已注册的系统服务
使用命令查看 system bus 上已经注册的总线有哪些:
# dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames
2514 : dbus_connection_send_with_reply_and_block try to send to org.freedesktop.DBus : org.freedesktop.DBus : Hello message 2514 : dbus_connection_send_with_reply_and_block try to send to org.freedesktop.DBus : org.freedesktop.DBus : ListNames message method return time=1690351431.030058 sender=org.freedesktop.DBus -> destination=:1.216 serial=3 reply_serial=2 array
[
...
string "org.freedesktop.DBus"
...
]
2.2 查看指定服务的接口列表
系统服务很多,篇幅限制省略一些。以 “org.freedesktop.DBus” 服务示例。通过服务名称,获取这个服务提供了哪些接口:
# dbus-send --system --print-reply=literal --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Introspectable.Introspect
命令参数的意义如下:
参数 | 说明 |
---|---|
–system | 指定发送消息到system bus,session bus 使用 --session 参数。 |
–print-reply=literal | 打印回复信息 |
–dest=org.freedesktop.DBus | dbus service name |
/org/freedesktop/DBus | path |
org.freedesktop.DBus.Introspectable.Introspect | interface和method的拼接 |
查询服务注册的接口
# dbus-send --system --print-reply=literal --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Introspectable.Introspect
...
<method name="StartServiceByName">
<arg direction="in" type="s"/>
<arg direction="in" type="u"/>
<arg direction="out" type="u"/>
</method>
...
返回的消息显示其中一个方法名称为 “StartServiceByName” ,有两个输出参数和一个返回值。参数类型有这些:
类型签名 | 类型 | 说明 |
---|---|---|
类型签名 | 类型 | 说明 |
s | 字符串 (String) | UTF-8编码的字符串 |
i | 有符号整数 (Signed Integer) | 32位有符号整数 |
u | 无符号整数 (Unsigned Integer) | 32位无符号整数 |
b | 布尔类型 (Boolean) | 取值为 true 或 false |
d | 双精度浮点数 (Double) | 64位浮点数 |
o | 对象路径 (Object Path) | 用于表示DBus对象的路径 |
g | 签名 (Signature) | 用于表示DBus类型签名字符串 |
y | 字节 (Byte) | 8位无符号整数 |
a{…} | 字典 (Dictionary) | 键值对的集合 |
v | 变体 (Variant) | 用于包装任意类型的值 |
() | 空元组 (Empty Tuple) | 表示没有参数 |
(type1 type2 …) | 元组 (Tuple) | 包含一组有序的参数 |
as | 字符串数组 (Array of Strings) | 由多个字符串组成的数组 |
ai | 有符号整数数组 (Array of Signed Integers) | 由多个有符号整数组成的数组 |
au | 无符号整数数组 (Array of Unsigned Integers) | 由多个无符号整数组成的数组 |
ab | 布尔数组 (Array of Booleans) | 由多个布尔值组成的数组 |
2.3 调用服务的方法
假如开发了一个系统配置的服务,可以设置键值对, D-Bus 服务的信息如下:
D-Bus 服务信息 | 值 |
---|---|
Service Name | com.myos.conf |
Path | /conf |
Interface | com.myos.conf |
其中注册了一个方法,原型如下:
bool setValue(string key, string value)
那调用此方法的命令就是这样的:
dbus-send --system --print-reply=literal --dest=com.myos.conf /conf com.myos.conf.setValue string:"language" string:"zh_CN"
上面的命令可以看出来如何给方法传递常规参数,除了基本类型,还支持数组、字典、variant(变体)。 |
2.4 发送服务信号
模拟服务发出信号,需指定–type为signal。参数传递和调用方法类似。并且不要打印回复,因为只有函数调用有回复。指定打印回复会默认–type为method_call。
下面命令将模拟发出一个void valueChanged(string key,string value)信号。
dbus-send --system --type=signal --dest=com.myos.conf /conf com.myos.conf.valueChanged string:"language" string:"zh_CN"
3. 命令 dbus-monitor 详解
dbus-monitor 是总线消息监视器。可以监控总线上的消息。官方文档DBUS-monitor。命令的全参数如下:
dbus-monitor [ --system | --session | --address ADDRESS ] [ --profile | --monitor | --pcap | --binary ] [ watch expressions ]
参数 | 说明 |
---|---|
[ --system | --session | --address ADDRESS ] | –system 系统总线 –session 会话总线(默认) –address ADDRESS:监视在ADDRESS处给定的任意消息总线 |
[ --profile | --monitor | --pcap | --binary ] | –profile:使用配置文件模式打印 –monitor:使用dbus-monitor模式打印(默认) –pcap:将PCAP文件头添加到输出的开头,并为每个消息添加PCAP消息头 –binary:二进制模式将输出整个二进制消息流 |
[ watch expressions ] | 如监控一个信号:“type=‘signal’,sender=‘org.gnome.TypingMonitor’,interface=‘org.gnome.TypingMonitor’” |
下面这个命令可以监控 org.gnome.TypingMonitor 服务 org.gnome.TypingMonitor 接口上发出的信号
dbus-monitor "type='signal',sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'"