当前位置: 首页 > news >正文

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.软件下载&#xff1a;DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 2.软件介绍 HBuilder是由DCloud&#xff08;数字天堂&#xff09;推出的一款面向HTML5的Web开发…...

vue3 + ts实现canvas绘制的waterfall

实际运行效果&#xff08;仅包含waterfall图表部分&#xff09; component.vue <template><div ref"heatmap" :style"{ height: props.containerHeight px }" /> </template><script setup> import ColorMap from "color…...

代码随想录算法训练营第四十四天

sad的一天&#xff0c;明天开始上班&#xff0c;而且娃还行&#xff0c;媳妇儿状态不稳定&#xff0c;太难了也&#xff01;&#xff01;&#xff01; 完全背包 #include<vector> #include<iostream> using namespace::std; int main(){int N;//种类int V;//空间ci…...

【3dmax笔记】027:配置修改器集、工具栏自定义与加载

文章目录 一、配置修改器集二、自定义工具栏三、加载工具栏 一、配置修改器集 可以把自己常用的修改命令放到右边框中的部分&#xff0c;便于自己的操作&#xff0c;省去了每次都要花半天时间找命令的尴尬。新建一个二维或者三维物体&#xff0c;点击修改面板&#xff0c;点击…...

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.…...

内存卡罢工,数据危机?别急,有救!

在日常生活和工作中&#xff0c;我们越来越依赖于各种电子设备来存储重要数据。其中&#xff0c;内存卡因其便携性和大容量而广受欢迎。然而&#xff0c;当内存卡突然损坏打不开时&#xff0c;我们该如何应对&#xff1f;本文将为您详细解析这一问题&#xff0c;并提供有效的解…...

python爬虫实战

import requests import json yesinput(输入页数&#xff1a;) 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 的标记性语言。它强调以数据为中心&#xff0c;并不是以标识语言为重点例如 SpringBoot 的配置文件 application.yml 也是一个 yaml 格式的文件 语法格式 通过缩进表示层级关系不能使用tab进行缩进&am…...

mac系统安装steam报错-解决办法

今天给虚拟机装了个苹果系统&#xff0c;然后想装个steam&#xff0c;从steam的官方下载安装steam_osx.dmg时&#xff0c;总是报“steam_osx已损坏&#xff0c;无法打开&#xff0c;请移动到废纸篓“。搜了一下找到了解决办法&#xff0c;这里记录一下。 双击steam_osx.dmg时&…...

这个簇状柱形图怎么添加百分比?

这个图表是excel默认的图表配色&#xff0c;有的人做出来都那个百分比&#xff0c;一起来做一个这样的图表。 1.插入图表 选中数据区域&#xff0c;点击 插入选项卡&#xff0c;在图表那一栏&#xff0c;点一下柱形图右侧那个倒三角&#xff0c;在弹邮对话框中&#xff0c;选…...

Tomact安装配置及使用(超详细)

文章目录 web相关知识概述web简介(了解)软件架构模式(掌握)BS&#xff1a;browser server 浏览器服务器CS&#xff1a;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文件,如何单独运行某个文件&#xff1f;n…...

使用request-try-notifyState流程实现UI控制与状态反馈的完整闭环

1. 前言 在Qt编程时&#xff0c;我们经常会在界面上添加一些按钮&#xff0c;当按钮被点击时&#xff0c;执行某段代码&#xff0c;例如显示一个对话框、关闭窗口&#xff0c;保存文件等等。 这种由UI控件触发某种信号&#xff0c;通过信号槽触发目的代码执行的场景非常多。这…...

屏蔽罩材质和厚度对屏蔽效能的影响

​ 一&#xff0e;屏蔽效能的影响因素 屏蔽效能的影响因素主要有两个方面&#xff1a;屏蔽材料的特性和厚度&#xff1b;如下图所示&#xff0c;电磁波经过不同媒介时&#xff0c;会在分界面形成反射&#xff0c;穿过界面的电磁波一部分被反射回去&#xff0c;这部分能量损失…...

Qt简单离线音乐播放器

有上传本地音乐文件&#xff0c;播放&#xff0c;暂停&#xff0c;拖拉进度条等功能的播放器。 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMediaPlayer> #include <QFileDialog> #include <QTime&g…...

微信小程序常用的api

基础API&#xff1a; wx.request&#xff1a;用于发起网络请求&#xff0c;支持GET、POST等方式&#xff0c;是获取网络数据的主要手段。wx.showToast&#xff1a;显示消息提示框&#xff0c;通常用于向用户展示操作成功、失败或加载中等状态。wx.showModal&#xff1a;显示模态…...

iOS xib布局

1.多次启动发现启动图和截屏的图片不一致,设置launch storyboard 不能到顶部 https://blog.csdn.net/u011960171/article/details/104053696/ 2.multipiler是比例&#xff0c;需要控制顺序1.视图&#xff0c;2父视图&#xff0c;选择宽度比例&#xff0c;默认是1 3.Aspect R…...

UNI-APP_拨打电话权限如何去掉,访问文件权限关闭

uniapp上架过程中一直提示&#xff1a;允许“app名”拨打电话和管理通话吗&#xff1f; uniapp配置文件&#xff1a;manifest.json “permissionPhoneState” : {“request” : “none”//拨打电话权限关闭 }, “permissionExternalStorage” : {“request” : “none”//访…...

Git知识点汇总表格总结

Git应该是现在各个做开发公司使用最广泛的版本管理工具了&#xff0c;还有一些公司可能用的SVN&#xff0c;不过总体来说&#xff0c;Git绝对是主流&#xff0c;SVN是集中式版本管理&#xff0c;使用起来相对Git更简单&#xff0c;不过功能相对Git也略显简略&#xff0c;Git的优…...

漫谈:C语言 奇葩的指针定义规则

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 C语言的语法很麻拐。 初学者的…...

spring boot中一般如何使用线程池

在Spring Boot中&#xff0c;线程池作为并发编程的核心工具&#xff0c;对于提升应用程序性能、优化资源利用和保证系统稳定性具有重要作用。本文将详细阐述如何在Spring Boot中正确使用线程池&#xff0c;包括配置参数、实例化、任务提交、监控及常见问题处理等环节&#xff0…...

Shader 纹理动画和顶点动画

一、内置变量--时间 要实现动画&#xff0c;我们需要把时间添加到计算当中&#xff0c;让画面可以随着时间变化而变化。在Unity Shader提供了如下关于时间的内置变量以便于在shader中访问时间实现各种动态效果。 名称类型描述_Timefloat4t是自该场景加载开始所经过的时间&…...

使用macof发起MAC地址泛洪攻击

使用macof发起MAC地址泛洪攻击 MAC地址泛洪攻击原理&#xff1a; MAC地址泛洪攻击是一种针对交换机的攻击方式&#xff0c;目的是监听同一局域网中用户的通信数据。交换机的工作核心&#xff1a;端口- MAC地址映射表。这张表记录了交换机每个端口和与之相连的主机MAC地址之间…...

力扣:1979. 找出数组的最大公约数(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;返回数组中最大数和最小数的 最大公约数 。 两个数的 最大公约数 是能够被两个数整除的最大正整数。 输入&#xff1a; nums [2,5,6…...

电瓶车充电桩:潜藏的暴利行业,简单入门到月入万元!

近几年来&#xff0c;电瓶车凭借其环保、经济特点已成为居民出行的必备工具之一。而促使电瓶车快速普及的原因之一即是电瓶车充电桩的普及。如果留心观察的话&#xff0c;相信大家都可以看出&#xff0c;国内大部分小区都已安装了充电桩设备&#xff0c;电瓶车充电桩已实现了大…...

mac监听 linux服务器性能可视化(Grafana+Promethus+Node_exporter)

Grafana和promethus(普罗米修斯)的安装和使用 监控系统的Prometheus类似于一个注册中心&#xff0c;我们可以只需要配置一个Prometheus,而在其他服务器&#xff0c;只需要安装node_exporter,它们的数据流转就是通过exporter采集数据信息&#xff0c;然后告诉prometheus它的位置…...

【负载均衡在线OJ项目日记】运行功能开发

目录 前言 运行功能开发分析 获取子进程运行信息 程序运行资源限制 运行功能开发代码 前言 上篇文章我们对客户端服务器传来的临时文件进行编译&#xff0c;这篇文章主要对编译成功的代码在我们的服务器运行这块功能的开发。 运行功能开发分析 在运行功能开发之前我们默…...

Qt | QLineEdit 类(行编辑器)

01、上节回顾 Qt | QComboBox(组合框)02、QLineEdit 1、QLineEdit 类是 QWidget 类的直接子类,该类实现了一个单行的 输入部件,即行编辑器,见右图 2、验证器(QValidator 类)和输入掩码简介:主要作用是验证用户输入的字符是否符合验证器 的要求,即限制对用户的输入,比…...

Mamba结构的Demo源码解读

文章目录 前言一、mamba结构构建辅助函数解读1、dataclass方法解读2、Norm归一化LayerNormRMSNormRMSNorm源码 3、nn.Parameter方法解读 二、mamba原理二、mamba模型构建1、主函数入口源码解读2、Mamba类源码解读 三、ResidualBlock的mamba结构源码解读四、MambaBlock构成Resid…...