Skip to content

Commit 7c4f184

Browse files
committed
new: add new article about dbus discovery
1 parent 82908b4 commit 7c4f184

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
+++
2+
date = '2025-11-21T17:56:21+08:00'
3+
draft = false
4+
title = 'Dbus 探索'
5+
+++
6+
7+
## 前言
8+
9+
之前想使用 `syfs` 监听电量变化失败,原因是 `sysfs` 不支持 `epoll` 之类的高级特性,所以还得隔几秒轮询,这对于精确度要求高的我来说是没法接受的,所以我不得不望向一个很熟悉但是陌生的东西————`Dbus`
10+
11+
## 概念
12+
13+
感觉 `Dbus` 是有点点像 `MQTT`,你看 `broker` 都出来了,都有订阅这一说法,但是又有点不同。
14+
15+
- **总线**: 包括系统总线和用户总线。前者可以报告系统状态,硬件上的状态(正是我们需要的);后者则在 `KDE` 的通知和特效之类上面大量使用,比如录屏的时候静音之类。
16+
- **总线名称**: 一个跟 `Dbus` 有关的服务启动了,这个服务下面提供的各种对象,全都是挂在这个总线名称下的。
17+
- **对象路径**: 服务提供的某些功能/实例,有点像 `unix` 的路径但是完全不一样,组织成面向对象的层次结构。
18+
- **接口名称**: 一个服务可以有多个接口,在不同的接口名称定义对象提供的方法、属性和信号。
19+
- **方法**: 客户端向服务端发起的同步请求,要求服务执行请求/获取状态然后返回请求。
20+
- **属性**: 客户端向服务端可以获取到的状态。
21+
- **信号**: 服务向总线上面发送通知,告知感兴趣的客户端某个事件发生了。
22+
- **订阅**: 客户端告诉总线对服务上面的某个对象的某个信号感兴趣。
23+
24+
`systemd``Dbus` 集成挺好的,可以监听某个总线上面的连接,如果客户端发出了请求但是服务没有启动,那么就会自动启动服务。这就像普通的服务上面的 `socket` 按需启动一样,也是把这套思路应用到了 `Dbus` 上面。
25+
26+
一般来说约定名字和对象路径中间的 `.``/` 对应,但是当然可以不遵守。
27+
28+
客户端可以手动向服务查询,对于用户,可以手动通过命令行获取信息;也可以由服务通过信号推送得到信息,这样就避免轮询造成的性能开销。
29+
30+
## 命令行使用
31+
32+
`systemd``busctl` 比较好理解,以这个工具为例。
33+
34+
`busctl` 无非就那几个参数,总线名称,对象路径,接口名称,然后按需调用/获取对应的对象。
35+
36+
### 自省
37+
38+
```shell
39+
busctl introspect <busName> <path>
40+
```
41+
42+
如果这个路径下的对象允许被自省的话,比如说 `UPower`
43+
44+
```shell
45+
❯ busctl introspect org.freedesktop.UPower /org/freedesktop/UPower
46+
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
47+
org.freedesktop.DBus.Introspectable interface - - -
48+
.Introspect method - s -
49+
org.freedesktop.DBus.Peer interface - - -
50+
.GetMachineId method - s -
51+
.Ping method - - -
52+
org.freedesktop.DBus.Properties interface - - -
53+
.Get method ss v -
54+
.GetAll method s a{sv} -
55+
.Set method ssv - -
56+
.PropertiesChanged signal sa{sv}as - -
57+
org.freedesktop.UPower interface - - -
58+
.EnumerateDevices method - ao -
59+
.GetCriticalAction method - s -
60+
.GetDisplayDevice method - o -
61+
.DaemonVersion property s "1.90.10" emits-change
62+
.LidIsClosed property b false emits-change
63+
.LidIsPresent property b true emits-change
64+
.OnBattery property b false emits-change
65+
.DeviceAdded signal o - -
66+
.DeviceRemoved signal o - -
67+
```
68+
69+
### 调用方法
70+
71+
那么显而易见了,直接调用:
72+
73+
```shell
74+
busctl call <busName> <path> <interface> <object> [param]
75+
```
76+
77+
得是 `method` 才能被调用,有的方法需要参数才能调用。
78+
79+
### 属性
80+
81+
属性既可以获取,在有权限的情况下可以设置。
82+
83+
```shell
84+
busctl get-property <busName> <path> <interface> <object>
85+
busctl set-property <busName> <path> <interface> <object>
86+
```
87+
88+
### 签名
89+
90+
获取对象或者调用方法传参的时候,要求签名匹配。这里其实是一些数据类型,根据对应的英文简称:
91+
92+
- `s`: 字符串
93+
- `b`: 布尔
94+
- `i`: 整形
95+
- `u`: 无符号整形
96+
- `d`: 双精度
97+
- `(a)o`: (数组式的)对象路径,用于查看其他对象。
98+
99+
传入参数是这样的,先输入类型,然后跟上你的数据,比如:
100+
101+
`s "hello" i 32`
102+
103+
### 简单的电量检测小工具
104+
105+
让 Gemini 用 QT 写了一个简单的电量监测系统,仅用于我这一台 chromebook:
106+
107+
[BatteryService](https://github.com/minortex/BatteryService)

0 commit comments

Comments
 (0)