Qt D-Bus 概述

D-Bus is an Inter-Process Communication (IPC) and Remote Procedure Calling (RPC) mechanism originally developed for Linux to replace existing and competing IPC solutions with one unified protocol. It was also designed to allow communication between system-level processes (such as printer and hardware driver services) and normal user processes.

它使用快速的二进制消息传递协议,适于同机通信 (由于它的低潜伏时间和低开销)。目前,其规范的定义由 freedesktop.org project and is available to all parties.

Communication, in general, happens through a central server application called the "bus" (hence the name), but direct application-to-application communication is also possible. When communicating on a bus, applications can query which other applications and services are available, as well as activate one on demand.

总线

D-Bus buses are used when many-to-many communication is desired. In order to achieve that, a central server is launched before any application can connect to the bus. This server is responsible for keeping track of the applications that are connected and for properly routing messages from their source to their destination.

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

For example, an application wishing to query the list of hardware devices attached to the computer will probably communicate to a service available on the system bus, while the service providing opening of the user's web browser will probably be found on the session bus.

On the system bus, you can also expect to find restrictions on what services each application is allowed to offer. Therefore, you can be reasonably certain that if a certain service is present, it's being offered by a trusted application.

概念

消息

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

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

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

服务名称

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

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

The format of a D-Bus service name is in fact very similar to a host name: it is a dot-separated sequence of letters and digits. The common practice is even to name your service name according to the domain name of the organization that defined that service.

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

org.freedesktop.DBus
					

对象路径

Like network hosts, applications provide specific services to other applications by exporting objects. Those objects are hierarchically organized, much like the parent-child relationship that classes derived from QObject possess. One difference, however, is that there is the concept of "root object", which all objects have as the ultimate parent.

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

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

接口

接口类似 C++ 抽象类和 Java 的 interface keyword and declare the "contract" that is established between caller and callee. That is, they establish the names of the methods, signals, and properties that are available as well as the behavior that is expected from either side when communication is established.

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

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

备忘单

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

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

调试

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

可以在每个应用程序的基础上启用此特征,通过设置 QDBUS_DEBUG 环境变量,在运行每个应用程序之前。例如,我们只可以启用调试,对于车在 D-Bus 远程控制车 example by running the controller and the car in the following way:

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

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