本文发布于Cylon的收藏册,转载请著名原文链接~

D-Bus是Linux使用的进程间通信机制,允许各个进程互相访问,而不需要为每个其他组件实现自定义代码。即使对于系统管理员来说,这也是一个相当深奥的主题,但它确实有助于解释linux的另一部分是如何工作的。

这里主要介绍 dbus-sendGDbus 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 bussession bus,通过使用 --system--session 选项来通过dbus-send 向系统总线或会话总线发送消息。如果两者都未指定,默认为**session bus*.

借此,顺道聊下 system bussession 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
--type=method_call 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 命令如何传入参数

1
2
3
4
5
6
7
8
 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

使用案例

如列出所有总线接口

1
2
3
4
5
6
dbus-send --session \
  --dest=org.freedesktop.DBus \
  --type=method_call \
  --print-reply \
  /org/freedesktop/DBus \
  org.freedesktop.DBus.ListNames

查看对方总线所支持的对象接口,org.freedesktop.DBus.Introspectableorg.freedesktop.DBus.Propertiesorg.freedesktop.PowerManagement。每个接口实现一些方法和信号。这些是你可以与之互动的东西。

1
2
3
4
5
6
dbus-send --session \
	--type=method_call \
	--print-reply \
	--dest=org.freedesktop.DBus \ 
	/ \
	org.freedesktop.DBus.Introspectable.Introspect

dbus-send,也支持调用远程总线接口,通过默认通过 DBUS_SESSION_BUS_ADDRESSDBUS_SYSTEM_BUS_ADDRESS,来指定远程的总线。

1
2
3
4
5
6
7
DBUS_SESSION_BUS_ADDRESS=""
dbus-send --session \
	--type=method_call \
	--print-reply \
	--dest=org.freedesktop.DBus \ 
	/ \
	org.freedesktop.DBus.Introspectable.Introspect

dbus-monitor

dbus-monitor 是一个可以监控 D-Bus 消息的命令行工具,。它可以调试和分析 D-Bus 通信间的数据包。

  1. 监视所有消息

要在控制台上监视所有 D-Bus 消息,可以使用以下命令:

1
dbus-monitor
  1. 监视某个特定接口
1
dbus-monitor interface="org.freedesktop.NetworkManager"
  1. 监视某个特定路径下的对象
1
dbus-monitor path="/org/freedesktop/NetworkManager"
  1. 监视某个特定接口和路径下的对象
1
2
dbus-monitor interface="org.freedesktop.NetworkManager" \ 
	path="/org/freedesktop/NetworkManager"
  1. 抓包输出到 Wireshark
1
dbus-monitor --pcap > 1.pcap

gdbus

gdbus是 GLib实现的dbus工具。较与 dbus-send,拥有更完整的功能。

introspect : 可以打印出对象的接口和属性值。对应对象的所有者需要实现org.freedesktop.DBus.Introspectable 的接口。使用 --xml选项,将打印返回的xml 格式。--recurse 选项可将其子级等打印,--only 选项仅打印具有属性的接口。

monitor: 类似于 dbus-monitor

call: 调用一个方法,传入的必须为 GVariant ,而相应的也为GVariant

emit: 发出信号。信号中包含的每个参数除字符串外都必须序列化为GVariant。

使用案例

1
2
3
4
5
6
gdbus introspect --system \
	--dest org.freedesktop.UPower \
	--object-path \
	/ \
	--recurse  \
	--only-properties 

通过call 来向一个dbus service发送信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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,)

监听一个服务的对象

1
2
3
4
gdbus monitor \
	--system \
	--dest org.freedesktop.NetworkManager \
	--object-path /org/freedesktop/NetworkManager/AccessPoint/4141

发送信号

1
2
3
gdbus emit --session \
	--object-path /foo \
	--signal org.bar.Foo "['foo', 'bar', 'baz']"

想特定进程发送信号,`–dest 为指定进程。

1
2
3
4
5
 gdbus emit \
 	--session \
 	--object-path /bar \
 	--signal org.bar.Bar someString \
 	--dest :1.42

检查配置文件语法

CentOS 7 (dbus 1.10),命令会启动一个dbus来验证配置文件的正确与否

1
dbus-launch --sh-syntax --config-file=/path/to/config > output.txt

higher

1
dbus-daemon --config-file=/path/to/config --print-syntax

本文发布于Cylon的收藏册,转载请著名原文链接~

链接:https://www.oomkill.com/2021/10/dbus-client-tutorial/

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。