Qt扫盲-Qt D-Bus概述
Qt D-Bus概述
- 一、概述
- 二、总线
- 三、相关概念
- 1. 消息
- 2. 服务名称
- 3. 对象的路径
- 4. 接口
- 5. 备忘单
- 四、调试
- 五、使用Qt D-Bus 适配器
- 1. 在 D-Bus 适配器中声明槽函数
- 1. 异步槽
- 2. 只输入槽
- 3. 输入输出槽
- 4. 自动回复
- 5. 延迟回复
一、概述
D-Bus是一种进程间通信(IPC)和远程过程调用(RPC)机制,最初是为Linux开发的,用一个统一的协议取代现有的和竞争的IPC解决方案。它还被设计为允许系统级进程(如打印机和硬件驱动程序服务)和普通用户进程之间的通信。
它使用快速的二进制消息传递协议,由于其低延迟和低开销,适合于同机通信。它的规范目前由 freedesktop.org 项目定义,所有各方都可以使用。
通信通常通过称为“总线”(因此得名)的中央服务器应用程序进行,但也可以直接进行应用程序到应用程序的通信。当在总线上通信时,应用程序可以查询哪些其他应用程序和服务可用,以及按需激活其中一个。
二、总线
D-Bus总线用于需要多对多通信的情况。为了实现这一点,在任何应用程序可以连接到总线之前启动一个中央服务器:该服务器负责跟踪连接的应用程序,并负责将消息从源路由到目的地。
此外,D-Bus还定义了两个众所周知的总线,称为系统总线和会话总线。这些总线的特殊之处在于它们具有良好定义的语义:一些服务被定义为可以在这些总线中的一个或两个中找到。
例如,希望查询附加到计算机上的硬件设备列表的应用程序可能会与系统总线上可用的服务通信,而提供打开用户web浏览器的服务可能会在会话总线上找到。
在系统总线上,还可以找到关于允许每个应用程序提供哪些服务的限制。因此,可以合理地确定,如果存在某个服务,它是由受信任的应用程序提供的。
三、相关概念
1. 消息
在底层,应用程序通过D-Bus相互发送消息进行通信。消息用于转发远程过程调用以及与之相关的应答和错误。当在总线上使用时,消息有目的地,这意味着它们只被路由到感兴趣的各方,避免了由于“蜂群”或广播造成的拥塞。
然而,有一种特殊类型的消息称为“信号消息”(基于Qt的信号和槽机制的概念),它没有预定义的目的地。由于其目的是在一对多上下文中使用,因此信号消息被设计为通过“选择加入”机制工作。
Qt D-Bus模块将消息的低级概念完全封装为Qt开发人员熟悉的更简单的面向对象方法。在大多数情况下,开发人员无需担心发送或接收消息。
2. 服务名称
当通过总线进行通信时,应用程序获得所谓的 “服务名称” :这是该应用程序选择被同一总线上的其他应用程序所知道的方式。通信总得知道是谁收谁发嘛。服务名称由D-Bus总线守护进程代理,用于将消息从一个应用程序路由到另一个应用程序。与服务名称类似的概念是IP地址和主机名:一台计算机通常有一个IP地址,并可能有一个或多个与之关联的主机名,这取决于它向网络提供的服务。
另一方面,如果不使用总线,也不会使用服务名称。如果我们再次将其与计算机网络进行比较,这将等同于点对点网络:由于对等点是已知的,因此不需要使用主机名来查找它或它的IP地址。
D-Bus服务名称的格式实际上与主机名非常相似:它是由点分隔的字母和数字序列。常见的做法甚至是根据定义该服务的组织的域名来命名服务名称。
例如,D-Bus服务是由freedesktop.org定义的,可以在总线上的服务名称下找到它:
org.freedesktop.DBus
就像 deepin中的部分代码用到的这种服务名称,也是用的域名表示方式,java中的很多包名也用的域名表示
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.interface()->isServiceRegistered("com.deepin.daemon.InputDevices")) {qDebug() << "DBusError" << "com.deepin.daemon.InputDevices";
return;
}// 监控全局鼠标信号。
sessionBus.connect("com.deepin.daemon.InputDevices","/com/deepin/api/XEventMonitor", "com.deepin.api.XEventMonitor", "ButtonPress",this, SLOT(ButtonPressEvent(int, int, int, QString)));
3. 对象的路径
与网络主机一样,应用程序通过导出对象向其他应用程序提供特定的服务。这些对象是分层组织的,很像从QObject派生的类所拥有的父子关系。然而,一个不同之处在于存在 “根对象” 的概念,所有对象都有作为最终父对象的根对象。
如果我们继续对Web服务进行类比,对象路径等同于URL的路径部分:

与它们类似,D-Bus中的对象路径的形式类似于文件系统中的路径名称:它们是由斜杠分隔的标签,每个标签由字母、数字和下划线(“_”)组成。它们必须总是以斜杠开始,不能以斜杠结束。
4. 接口
接口类似于c++抽象类和Java的interface关键字,并声明了在调用者和被调用者之间建立的“契约”。也就是说,它们建立了可用的方法、信号和属性的名称,以及在建立通信时期望的任何一方的行为。
Qt在它的插件系统中使用了一个非常相似的机制:c++中的基类通过Q_DECLARE_INTERFACE()宏与一个唯一标识符相关联。
实际上,D-Bus接口名称的命名方式类似于Qt插件系统所建议的:一个标识符通常由定义该接口的实体的域名构造而成。
5. 备忘单
为方便记忆命名格式及其用途,可使用下表:
| d - bus概念 | 类比 | 名字的格式 |
|---|---|---|
| Service name 服务名称 | 网络主机名 | 点分隔(“看起来像主机名”) |
| Object path 对象路径 | URL路径组件 | 斜杠分隔(“看起来像一条路径”) |
| Interface 接口 | 插件标识符 | 以圆点分隔 |
四、调试
在开发使用D-Bus的应用程序时,有时能够查看每个应用程序通过总线发送和接收的消息的相关信息是很有用的。
通过在运行每个应用程序之前设置QDBUS_DEBUG环境变量,可以在每个应用程序的基础上启用该特性。例如,在D-Bus遥控汽车示例中,我们可以通过以下方式运行控制器和汽车,使能仅对汽车进行调试:
examples/dbus/remotecontrolledcar/controller/controller &QDBUS_DEBUG=1 examples/dbus/remotecontrolledcar/car/car &
有关消息的信息将写入启动应用程序的控制台中。
五、使用Qt D-Bus 适配器
适配器是附加到任何qobject派生类的特殊类,并使用D-Bus提供与外部世界的接口。适配器旨在成为轻量级类,其主要目的是中继对真实对象的调用和来自真实对象的调用,可能会验证或转换来自外部世界的输入,从而保护真实对象。
与多重继承不同,适配器可以随时添加到任何对象(但不能删除),这在导出现有类时提供了更大的灵活性。适配器的另一个优点是在不同接口中的同名方法中提供类似但不相同的功能,在向对象添加新版本的标准接口时,这种情况非常常见。
为了使用适配器,必须创建继承QDBusAbstractAdaptor的类。由于这是一个标准的qobject派生类,Q_OBJECT宏必须出现在声明中,源文件必须用moc工具处理。类还必须包含一个带有“D-Bus Interface”名称的Q_CLASSINFO条目,声明它要导出的接口。每个类只支持一个条目。
类中的任何公共槽都可以通过MethodCall类型的消息通过总线访问。(更多信息请参见声明D-Bus适配器的槽函数)。课堂上的信号将通过D-Bus自动传递。然而,并非所有类型都允许信号或槽的参数列表:参见Qt D-Bus类型系统了解更多信息。
此外,使用Q_PROPERTY声明的任何属性都将通过D-Bus上的Properties接口自动公开。由于QObject属性系统不允许非可读属性,因此不可能使用适配器声明只写属性。
1. 在 D-Bus 适配器中声明槽函数
D-Bus适配器中的槽函数就像普通的公共槽函数一样被声明,但是它们的参数必须遵循一定的规则(参见Qt D-Bus类型系统了解更多信息)。如果槽函数的参数不符合这些规则,或者槽函数不是公共的,那么D-Bus将无法访问这些槽函数。
槽可以有一个const QDBusMessage &类型的参数,它必须出现在输入参数列表的末尾,在任何输出参数之前。如果存在此参数,将使用正在处理的当前消息的副本初始化,这允许被调用方获取有关调用方的信息,例如其连接名称。
槽有三种类型:
- 异步槽
- 只输入槽
- 输入和输出槽
1. 异步槽
异步槽通常不向调用者返回任何应答。因此,它们不能接受任何输出参数。在大多数情况下,到运行槽的第一行时,调用方函数已经恢复工作。
然而,槽函数不能依赖于这种行为。调度和消息调度问题可能会改变槽函数运行的顺序。打算与调用者同步的代码应该提供自己的同步方法。
异步槽由方法签名中的关键字Q_NOREPLY标记,位于void返回类型和槽名之前。D-Bus Complex乒乓示例中的quit()槽函数就是这样的一个例子。
2. 只输入槽
仅输入槽是普通槽,它接受按值或常量引用传递的参数。然而,与异步槽不同,调用方通常在恢复操作之前等待被调用方完成。因此,非异步槽函数不应该阻塞,或者应该在文档中说明它们可能会阻塞。
只有输入的槽在它们的签名中没有特殊的标记,除了它们只接受通过值或常量引用传递的参数。槽可以选择将QDBusMessage参数作为最后一个参数,该参数可用于执行对方法调用消息的附加分析。
3. 输入输出槽
与仅输入槽一样,输入-输出槽是调用者等待回复的槽。但是,与只输入的应答不同,此应答将包含数据。输出数据的槽可能包含非常量引用,也可能返回一个值。但是,输出参数必须全部出现在参数列表的末尾,并且输入参数不能交错。可选地,QDBusMessage参数可能出现在输入和输出参数之间。
4. 自动回复
方法应答是由Qt D-Bus实现与输出参数(如果有的话)的内容一起自动生成的。槽函数不需要考虑构造适当的QDBusMessage对象并通过连接发送它们。
然而,这样做的可能性仍然存在。如果槽发现它需要发送一个特殊的回复,甚至是一个错误,它可以在QDBusMessage参数上使用QDBusMessage::createReply()或QDBusMessage::createErrorReply(),并使用QDBusConnection::send()发送它。如果槽函数这样做了,Qt D-Bus实现将不会生成任何应答。
警告:当调用者调用方法并等待应答时,它将只等待有限的时间。打算花费很长时间来完成的槽函数应该在文档中明确这一事实,以便调用者适当地设置更高的超时。
5. 延迟回复
在某些情况下,被调用的槽可能无法立即处理请求。当请求涉及可能阻塞的I/O或网络操作时,这种情况经常发生。
如果是这种情况,slot应该将控制返回给应用程序的主循环,以避免冻结用户界面,并在以后恢复该进程。要实现这一点,它应该利用输入参数列表末尾的额外QDBusMessage参数,并请求延迟回复。
为此,我们编写一个将请求数据存储在持久结构中的槽,并使用QDBusMessage::setDelayedReply(true)向调用者指示稍后将发送响应。
struct RequestData{QString request;QString processedData;QDBusMessage reply;};QString processRequest(const QString &request, const QDBusMessage &message){RequestData *data = new RequestData;data->request = request;message.setDelayedReply(true);data->reply = message.createReply();QDBusConnection::sessionBus().send(data->reply);appendRequest(data);return QString();}
需要使用QDBusConnection::sessionBus().send(data->reply)来显式地通知调用者响应将被延迟。在这种情况下,返回值并不重要;我们返回一个任意值来满足编译器。
当请求被处理并且应答可用时,应该使用获得的QDBusMessage对象发送应答。在我们的示例中,回复代码可能如下所示:
void sendReply(RequestData *data){// data->processedData has been initialized with the request's replyQDBusMessage &reply = &data->reply;// send the reply over D-Bus:reply << data->processedData;QDBusConnection::sessionBus().send(reply);// dispose of the transaction datadelete data;}
在这个例子中可以看到,当延迟应答到位时,从槽返回的值将被Qt D-Bus忽略。它们仅用于在与远程应用程序通信适配器描述时确定槽函数的签名,或者在槽函数中的代码决定不使用延迟应答的情况下。
延迟的回复本身是通过调用QDBusMessage::reply()从Qt D-Bus请求的。然后,被调用的代码负责最终向调用方发送应答。
警告-当调用者调用方法并等待应答时,它将只等待有限的时间。打算花费很长时间来完成的槽函数应该在文档中明确这一事实,以便调用者适当地设置更高的超时。
相关文章:
Qt扫盲-Qt D-Bus概述
Qt D-Bus概述 一、概述二、总线三、相关概念1. 消息2. 服务名称3. 对象的路径4. 接口5. 备忘单 四、调试五、使用Qt D-Bus 适配器1. 在 D-Bus 适配器中声明槽函数1. 异步槽2. 只输入槽3. 输入输出槽4. 自动回复5. 延迟回复 一、概述 D-Bus是一种进程间通信(IPC)和远程过程调用…...
懒洋洋作业讲解
懒洋洋作业讲解 环境配置 1.软件下载:DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 2.软件介绍 HBuilder是由DCloud(数字天堂)推出的一款面向HTML5的Web开发…...
vue3 + ts实现canvas绘制的waterfall
实际运行效果(仅包含waterfall图表部分) component.vue <template><div ref"heatmap" :style"{ height: props.containerHeight px }" /> </template><script setup> import ColorMap from "color…...
代码随想录算法训练营第四十四天
sad的一天,明天开始上班,而且娃还行,媳妇儿状态不稳定,太难了也!!! 完全背包 #include<vector> #include<iostream> using namespace::std; int main(){int N;//种类int V;//空间ci…...
【3dmax笔记】027:配置修改器集、工具栏自定义与加载
文章目录 一、配置修改器集二、自定义工具栏三、加载工具栏 一、配置修改器集 可以把自己常用的修改命令放到右边框中的部分,便于自己的操作,省去了每次都要花半天时间找命令的尴尬。新建一个二维或者三维物体,点击修改面板,点击…...
Reactor模型详解
目录 1.概述 2.Single Reactor 3.muduo库的Multiple Reactors模型如下 1.概述 维基百科对Reactor模型的解释 The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs.…...
内存卡罢工,数据危机?别急,有救!
在日常生活和工作中,我们越来越依赖于各种电子设备来存储重要数据。其中,内存卡因其便携性和大容量而广受欢迎。然而,当内存卡突然损坏打不开时,我们该如何应对?本文将为您详细解析这一问题,并提供有效的解…...
python爬虫实战
import requests import json yesinput(输入页数:) yesint(yes)headers {"accept": "application/json, text/plain, */*","accept-language": "zh-CN,zh;q0.9","content-type": "application/json",…...
k8s 资源文件参数介绍
Kubernetes资源文件yaml参数介绍 yaml 介绍 yaml 是一个类似 XML、JSON 的标记性语言。它强调以数据为中心,并不是以标识语言为重点例如 SpringBoot 的配置文件 application.yml 也是一个 yaml 格式的文件 语法格式 通过缩进表示层级关系不能使用tab进行缩进&am…...
mac系统安装steam报错-解决办法
今天给虚拟机装了个苹果系统,然后想装个steam,从steam的官方下载安装steam_osx.dmg时,总是报“steam_osx已损坏,无法打开,请移动到废纸篓“。搜了一下找到了解决办法,这里记录一下。 双击steam_osx.dmg时&…...
这个簇状柱形图怎么添加百分比?
这个图表是excel默认的图表配色,有的人做出来都那个百分比,一起来做一个这样的图表。 1.插入图表 选中数据区域,点击 插入选项卡,在图表那一栏,点一下柱形图右侧那个倒三角,在弹邮对话框中,选…...
Tomact安装配置及使用(超详细)
文章目录 web相关知识概述web简介(了解)软件架构模式(掌握)BS:browser server 浏览器服务器CS:client server 客户端服务器 B/S和C/S通信模式特点(重要)web资源(理解)资源分类 URL请求路径(理解)作用介绍格式浏览器通过url访问服务器的过程 服务器(掌握)…...
web后端——netbeans ide +jsp+servlet开发学习总结
目录 jsp基础 netbeans开发工具问题HTTP Status 405 - HTTP method POST is not supported......netbeans 提示无法启动GlassFish Server 4.1.1:服务器未运行时, HTTP 或 HTTPS 监听程序端口已被占用404 问题netbeans中项目中有多个html文件,如何单独运行某个文件?n…...
使用request-try-notifyState流程实现UI控制与状态反馈的完整闭环
1. 前言 在Qt编程时,我们经常会在界面上添加一些按钮,当按钮被点击时,执行某段代码,例如显示一个对话框、关闭窗口,保存文件等等。 这种由UI控件触发某种信号,通过信号槽触发目的代码执行的场景非常多。这…...
屏蔽罩材质和厚度对屏蔽效能的影响
一.屏蔽效能的影响因素 屏蔽效能的影响因素主要有两个方面:屏蔽材料的特性和厚度;如下图所示,电磁波经过不同媒介时,会在分界面形成反射,穿过界面的电磁波一部分被反射回去,这部分能量损失…...
Qt简单离线音乐播放器
有上传本地音乐文件,播放,暂停,拖拉进度条等功能的播放器。 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMediaPlayer> #include <QFileDialog> #include <QTime&g…...
微信小程序常用的api
基础API: wx.request:用于发起网络请求,支持GET、POST等方式,是获取网络数据的主要手段。wx.showToast:显示消息提示框,通常用于向用户展示操作成功、失败或加载中等状态。wx.showModal:显示模态…...
iOS xib布局
1.多次启动发现启动图和截屏的图片不一致,设置launch storyboard 不能到顶部 https://blog.csdn.net/u011960171/article/details/104053696/ 2.multipiler是比例,需要控制顺序1.视图,2父视图,选择宽度比例,默认是1 3.Aspect R…...
UNI-APP_拨打电话权限如何去掉,访问文件权限关闭
uniapp上架过程中一直提示:允许“app名”拨打电话和管理通话吗? uniapp配置文件:manifest.json “permissionPhoneState” : {“request” : “none”//拨打电话权限关闭 }, “permissionExternalStorage” : {“request” : “none”//访…...
Git知识点汇总表格总结
Git应该是现在各个做开发公司使用最广泛的版本管理工具了,还有一些公司可能用的SVN,不过总体来说,Git绝对是主流,SVN是集中式版本管理,使用起来相对Git更简单,不过功能相对Git也略显简略,Git的优…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
