Qt D-Bus

介绍

D-Bus 是最初为 Linux 开发的 IPC (进程间通信) 和 RPC (远程过程调用) 机制,采用一统一协议替换现有-竞争 IPC 解决方案。它还被设计成允许系统级进程 (譬如:打印机和硬件驱动程序服务) 和普通用户进程之间通信。

它使用快速的二进制消息传递协议,适于同机通信 (由于它的低潜伏时间和低开销)。目前,其规范的定义由 freedesktop.org 工程,且所有各方可用。

通信一般透过称为 Bus (总线,因此得名) 的中心服务器应用程序发生,但直接应用程序到应用程序的通信也是可能的。当在 Bus (总线) 上进行通信时,应用程序可以查询哪些其它应用程序和服务是可用的,还可按需激活一个。

总线

D-Bus 总线用于当期望多对多通信时。为达成这,需发起中心服务器在任何应用程序可以连接到总线之前:此服务器负责跟踪连接的应用程序,并将消息从源正确路由到其目的地。

此外,D-Bus 定义了 2 个众所周知的总线 (称为系统总线和会话总线)。这些总线的特殊意义是它们具有定义良好的语义:一些服务被定义成能在其中一个或两个总线中被找到。

例如,希望查询附加到计算机硬件设备列表的应用程序,可能与系统总线中可用的服务进行通信,而提供打开用户 Web 浏览器的服务则可能在会话总线上被找到。

在系统总线,还可以找到对各应用程序允许提供什么服务的限定期望。因此,可合理确定,若存在某种服务,则该服务是由受信任的应用程序提供的。

概念

消息

在较低级别,应用程序通过 D-Bus 相互发送消息进行通信。使用消息能中继远程过程调用、及与它们关联的回复和错误。当通过总线使用时,消息具有目的地,这意味着它们仅能路由到感兴趣各方,避免由于蜂拥 (或广播) 的拥塞。

一种特殊消息,称为信号消息 (概念基于 Qt 的 信号和槽 机制),不管怎样,没有预定义目的地。由于其目的是在一对多上下文中使用,所以信号消息被设计成在选择加入机制下工作。

Qt D-Bus 模块将低级消息概念完全封装成 Qt 开发者所熟悉的更简单、面向对象的方式。在大多数情况下,开发者无需担心消息的发送或接收。

服务名称

当通过总线通信时,应用程序获得所谓的服务名称:这就是该应用程序选择被同一总线中,其它应用程序知道的方式。服务名称由 D-Bus 总线代理程序守护,用于将消息从一个应用程序路由到另一个应用程序。与服务名称类似的概念是 IP 地址和主机名:根据计算机提供给网络的服务,一台计算机通常具有一个 IP 地址,且可能具有一个或多个与其关联的主机名。

另一方面,若不使用总线,也不会使用服务名称。若再将其与计算机网络进行比较,这相当于点对点网络:由于对等方是已知的,因此不需要使用主机名来查找它 (或其 IP 地址)。

D-Bus 服务名称的格式实际上非常类似于主机名:它是由点分隔的字母和数字的序列。常见实践甚至是根据定义该服务的组织的域名,来命名一服务名称。

例如,D-Bus 服务的定义通过 freedesktop.org 且可以在总线中找到以下服务名称:

org.freedesktop.DBus
							

对象路径

像网络主机,应用程序通过导出对象为其它应用程序提供特定服务。这些对象按层次组织,非常类似类的父子关系,派生自 QObject 占有。不管怎样,一种区别是存在根对象概念 (所有对象具有最终父级)。

若继续与 Web 服务进行类比,对象路径等同于 URL 的路径部分:

像它们,D-Bus 对象路径的形成类似文件系统路径名:它们是以斜杠分隔的标签,各标签的组成由字母、数字及下划线字符 ( _ )。它们必须始终以斜杠开头,且不能以斜杠结尾。

接口

接口类似 C++ 抽象类和 Java 的 interface 关键词和声明在调用者和被调用者之间建立的契约。也就是说,它们建立的方法、信号及特性的名称是可用的,及行为是双方期望的当建立通信时。

Qt 使用非常类似的机制在其 插件系统 :C++ 中的基类关联唯一标识符,通过方式 Q_DECLARE_INTERFACE () 宏。

实际上,D-Bus 接口名称的命名方式与 Qt 插件系统的建议类似:标识符的构造通常来自定义该接口的实体的域名。

备忘单

为便于记住命名格式及其用途,可以使用下表:

D-Bus 概念 类比 名称格式
服务名称 网络主机名 点分隔 (看起来像主机名)
对象路径 URL 路径分量 斜杠分隔 (看起来像路径)
接口 插件标识符 点分隔

调试

在使用 D-Bus 开发应用程序时,有时,能够查看各应用程序跨总线发送和接收的消息的相关信息是有用的。

可以在每个应用程序的基础上启用此特征,通过设置 QDBUS_DEBUG 环境变量,在运行每个应用程序之前。例如,我们只可以启用调试,对于车在 D-Bus 远程控制车范例 通过以下方式运行控制器和车:

examples/dbus/remotecontrolledcar/controller/controller &
QDBUS_DEBUG=1 examples/dbus/remotecontrolledcar/car/car &
							

有关消息的信息会被写入到发起应用程序的控制台。

使用模块

使用 Qt 模块要求直接或透过其它依赖链接到模块库。一些构建工具为此有贡献支持,包括 CMake and qmake .

构建采用 CMake

使用 find_package() 命令去定位所需模块组件,在 Qt6 包:

find_package(Qt6 COMPONENTS DBus REQUIRED)
target_link_libraries(mytarget PRIVATE Qt6::DBus)
							

另请参阅 构建采用 CMake 概述。

采用 qmake 构建

要配置采用 qmake 构建模块,添加模块作为值为 QT 变量在工程 .pro 文件:


							

模块演变

Qt D-Bus 的变化 列出了 Qt 的 Qt 6 系列在模块 API 和功能方面所做出的重要改变。

许可和归属

Qt D-Bus 模块在商业许可下是可用的来自 Qt 公司 。此外,它在自由软件许可下也是可用的: GNU LGPL (次一般公共许可) 第 3 版 ,或 GNU GPL (一般公共许可) 第 2 版 。见 Qt 许可 进一步了解细节。

此外,Qt 6.1.1 中的 Qt D-Bus 可能包含的第 3 方模块遵循以下准许许可:

libdus-1 头,dbus 第 1.13.12 版

学术免费许可第 2.1 版,或 GNU GPL (一般公共许可) 第 2.0 版或更高版本

延伸阅读

以下文档包含 Qt 的 D-Bus 集成特征的有关信息,且提供通过总线发送和接收类型信息的机制的有关细节: