Linux 桌面上的 D-Bus 问题
Source: Hacker News
什么是 D‑Bus?
每个人都听说过 D‑Bus,但它到底是什么?
D‑Bus 的想法很简单:让应用、服务以及其他 事物 以一种其他应用可以在同一个地方(总线)找到它们的方式公开方法或属性。
例如,一个天气监测服务可以在总线上公开天气 API。任何应用都可以发现该服务并使用它,而不是每个应用各自实现与天气提供商的通信。
出了什么问题?
D‑Bus 是一个 宽容的、无组织的、容错的 总线。这些特性导致了根本性的概念性问题:
- 总线上的对象可以注册任何它们想要的内容。
- 对象可以以任何方式、在任何时间调用任何它们想要的内容。
- 协议允许,甚至鼓励,供应商特定的未检查垃圾。
在实践中,这导致了 “垃圾进,垃圾出”。
D‑Bus 标准
第 1 部分
应用需要通信,但文档分散、未完成或难以阅读,许多客户端根本不理会它。
以下是现有(常常令人困惑)文档的几个例子:



标准一团糟,实施者经常不遵循它们。
第 2 部分
即使有规范,也几乎没有强制执行。带有任意数据的匿名调用很常见。
故事:在编写 xdg‑desktop‑portal‑hyprland 时,我遵循了 portal 文档并实现了所需的 D‑Bus 协议。实现能够工作,但当我加入“恢复令牌”(一个符合规范的机制)时,没有任何应用使用它。每个人都创建了自己的未文档化变体,迫使我改用 KDE 的实现。
规范甚至在 SelectSources 和 Start 上宣传了 restore_token 属性,但没有应用使用它;它们使用了不同的 restore_data 字段。
第 3 部分
许多协议依赖 变体(例如 a{sv} —— 字符串‑变体对的数组)。允许如此宽松的类型数据会鼓励应用发送随机信息并期望对方能够解释,这种模式已经导致了反复的失败(类似于 X 原子)。
第 4 部分
权限实际上是缺失的。每个人都可以看到所有内容并调用任何方法。没有统一的“拒绝”概念;每个协议必须自行定义错误处理。安全性的缺失是 Flatpak 应用无法看到会话总线的主要原因。
第 5 部分
像 kwallet 或 gnome‑keyring 这样的密钥存储可以通过密码解锁,在磁盘上加密数据。然而,一旦解锁,任何在总线上的应用都可以在用户不知情的情况下读取所有存储的密钥。
受够了
我已经对 D‑Bus 感到厌倦。虽然会话(以及后来的系统)总线对我的生态系统有用,但我无法容忍 D‑Bus 目前的状态。
因此,我决定从头创建一个新总线,避免 D‑Bus 的诸多问题设计选择。
XKCD 927
很多人在实现新系统时会引用这幅 XKCD 漫画,但情况不同。使用 Wayland 时,放弃 X11 意味着你不能在同一时间运行 X11 会话和 Wayland 会话。然而,你可以同时运行多个 D‑Bus‑like 会话总线(两个、三个或更多)。一个代理客户端可以在它们之间进行翻译,从而实现渐进式迁移。
Wire
我首先关注的组件是 hyprwire,它是 Hypr* 工具(如 hyprlauncher、hyprpaper 等)的线协议。
线协议的关键优势:
- 一致性: 类型和消息参数受到强制约束;没有
a{sv}或 “随便发点什么”。 - 简洁性: 快速且直接;没有复杂的结构体类型。
- 速度: 握手和协议交换迅速;连接建立非常快。
Hyprwire 已经在 hyprpaper、hyprlauncher 和 hyprctl 的部分功能中用于 IPC。
Bus
总线本身叫 hyprtavern。它并不是 D‑Bus 的直接替代品,但用途相似。
- 应用在总线上注册 对象,公开这些对象所定义的协议和关键属性。
- 其他应用可以通过连接总线来发现这些对象。
在此模型中,hyprtavern 像一家酒馆:每个应用都是客户端,可以与其他应用注册的对象进行交互。