1.什么是D-Bus

D-Bus是一种高级的进程间通信机制,它由freedesktop.org项目提供,使用GPL许可证发行。D-Bus最主要的用途是在Linux桌面环境为进程提供通信,同时能将Linux桌面环境和Linux内核事件作为消息传递到进程。注册后的进程可通过总线接收或传递消息,进程也可注册后等待内核事件响应,例如等待网络状态的转变或者计算机发出关机指令。目前,D-Bus已被大多数Linux发行版所采用,开发者可使用D-Bus实现各种复杂的进程间通信任务。

2.D-Bus的相关概念

D-Bus是一个消息总线系统,其功能已涵盖进程间通信的所有需求,并具备一些特殊的用途。D-Bus是三层架构的进程间通信系统,其中包括:

接口层:接口层由函数库libdbus提供,进程可通过该库使用D-Bus的能力。

总线层:总线层实际上是由D-Bus总线守护进程提供的。它在Linux系统启动时运行,负责进程间的消息路由和传递,其中包括Linux内核和Linux桌面环境的消息传递。

包装层:包装层一系列基于特定应用程序框架的Wrapper。

Linux发行版都会提供两种Message Bus:System Bus和Session Bus。System Bus 主要用于内核和一些系统全局的service之间通信;Session Bus 主要用于桌面应用程序之间的通信。

dbus的通信结构图如下图所示:

dbus总线通信,通过分层分级的方式实现各种各样的复杂进程间通信。dbus通信分为三层:Service、Object、Interface。

Service

应用程序注册的形如"com.mycompany.myapp"的名字为程序与D-bus总线的连接的名称,用来对应用程序进行定位。相当于对程序的连接起了一个比较好记得地址,类似于网站的域名。应用程序和DBus之间的连接也被称为Service。

Object

当应用程序连接到Message Bus上时,该应用程序可以在Bus上创建多个Object(我们可以把D-Bus的object理解成面向对象语言里的object)。Service通过Object 为其他应用程序提供访问接口。因为在Message Bus上,一个应用程序可以对应多个Object,所以不同的Object必须由Object Path(类似于文件系统的路径)来区分。Object Path的格式如"/component/user"。

Serivce和Object Path之间相互独立,没有任何关联,注册时可以根据需要命名.

Interface

D-Bus通过Signal/Method来发送和接收Message。Signal/Method可以理解为QT中的Signal/Slot这个概念。一个Object可以提供多个Method/Signal,这些Method/Signal的集合又组成了Interface。

因此,D-Bus的这些概念从大到小可以表示为:dbus->Service->Object->[Interface]-> Method/Signal。

在程序之间的通讯过程中,我们通过Service,Object,Interface组合起来,找到信号需要执行的应用程序中的代码。

3.D-Bus在Qt中的使用方法

服务端的程序

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "handler.h"namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private:Ui::Widget *ui;Handler m_handler;public slots:void service_get(QString st);void send_msg();
signals:void send_to_client(QString);};#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include "handler.h"
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>
#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);QDBusConnection bus = QDBusConnection::sessionBus();//注册名称为domm.test的服务QDBusConnection::sessionBus().unregisterService("domm.test");if(!bus.registerService("domm.test")){qDebug() << bus.lastError().message();exit(1);}//注册名路径为/ceshi/registry的Object//导出对应的槽函数和信号bus.registerObject("/ceshi/registry", this,QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals);//将/ceshi/registry对象com.citos.test2接口下的send_to_service信号//关联对应的槽函数      QDBusConnection::sessionBus().connect(QString(""),QString("/ceshi/registry"),"com.citos.test2","send_to_service",this,SLOT(service_get(QString)));connect(ui->sendBtn, SIGNAL(clicked(bool)),this ,SLOT(send_msg()));setWindowTitle("服务端");
}Widget::~Widget()
{delete ui;
}void Widget::service_get(QString st)
{ui->receive_LineEdit->clear();ui->receive_LineEdit->setText(st);
}void Widget::send_msg()
{QString content = ui->send_LineEdit->text();//创建针对/ceshi/registry对象中com.citos.test1接口下的//send_to_client信号QDBusMessage message = QDBusMessage::createSignal("/ceshi/registry","com.citos.test1","send_to_client");message << content;QDBusConnection::sessionBus().send(message);ui->send_LineEdit->clear();
}
#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

客户端程序

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QtDBus/QDBusConnection>namespace Ui {
class Widget;
}
class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void Client_get(QString st);void Send_Msg();private:Ui::Widget *ui;
};#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//将Serivce(domm.test)Object(/ceshi/registry)Interface(com.citos.test2)//发送的信号send_to_client关联到槽函数Client_getQDBusConnection::sessionBus().connect(QString("domm.test"), QString("/ceshi/registry"),"com.citos.test2","send_to_client",this,SLOT(Client_get(QString)));connect(ui->sendBtn, SIGNAL(clicked(bool)),this, SLOT(Send_Msg()));setWindowTitle("客户端");
}Widget::~Widget()
{delete ui;
}void Widget::Send_Msg()
{QString msg = ui->sendLineEdit->text();//发送Object(/ceshi/registry)Interface(com.citos.test2)下的信号//send_to_service到服务端QDBusMessage dbusMsg = QDBusMessage::createSignal("/ceshi/registry","com.citos.test2", "send_to_service");dbusMsg << msg;QDBusConnection::sessionBus().send(dbusMsg);ui->sendLineEdit->clear();
}void Widget::Client_get(QString st)
{ui->ReceiveLineEdit->clear();ui->ReceiveLineEdit->setText(st);
}
#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

4.dbus调试工具

//linux下通过dbus-monitor命令来监测系统的dbus消息
dbus-monitor [--system | --session | --address ADDRESS]
[--monitor | --profile | --pcap | --binary ] [watch expressions]--system   监控系统的dbus消息
--session  监控所有的会话消息(默认)
--profile  使用简要的输出格式
--monitor  使用监控的输出格式(默认)//监听特定服务特定对象特定接口发送的特定消息
//监听org.cehsi.info服务,在interface接口下发送的信号
dbus-monitor "type='signal',sender='org.cehi.info',interface='org.cehsi.test'"
type:调用的类型,包括:method_call. signal
sender:用来筛选发送者
interface:用来指定对应的接口

dbus总线通信的原理和使用相关推荐

  1. TJA1050T CAN总线通信硬件原理

    CAN接口设计: CAN总线是一种有效支持分布式控制和实时控制的串行通信网络,以其高性能和高可靠性在自动控制领域得到了广泛的应用.为提高系统的驱动能力,增大通信距离,实际应用中多采用Philips公司 ...

  2. CAN总线通信原理分析

    摘要:介绍了控制器局域网总线(CAN总线)的应用特性以及将其应用于具体的工程项目时CAN总线系统的分层结构及各层的主要功能.基于CAN总线系统结构构成,通过工程实践的具体应用以及对CAN控制器及收发器 ...

  3. Linux -dbus总线

    下载编译dbus 下载https://dbus.freedesktop.org/releases/dbus/ dbussrc1.14.0-Linux文档类资源-CSDN下载 dbus-1.14.0.t ...

  4. can协议crc计算_CAN总线通信的CRC校验方法

    数据校验是为保证数据的完整性进行的一种验证操作.CAN通信采用CRC校验作为一种重要的错误检测手段,是节点判断CAN帧信息的完整性并产生确认应答的依据. 在现场总线通信和控制的实际应用中,工业应用环境 ...

  5. CAN总线通信学习笔记

    CAN总线通信学习笔记 完整笔记链接:https://mubu.com/doc/67Rn6yaozhS CAN总线笔记目录 定义 底层原理 CAN信号传输 发送 接收 CAN总线结构.特点.分类 CA ...

  6. Linux DBUS总线

    D-Bus三层架构 D-Bus是一个为应用程序间通信的消息总线系统, 用于进程之间的通信.它是个3层架构的IPC 系统,包括: 1.函数库libdbus ,用于两个应用程序互相联系和交互消息. 2.一 ...

  7. 【STC8A8K64S4A12开发板】—RS485总线通信

    版权声明:本文为博主原创文章,转载请附上原文出处链接. 文章目录 前言 一.硬件设计 1.开发板串口硬件电路 2.RS485电气性能 3.RS485通信协议 4.RS485电路设计 二.软件设计 1. ...

  8. 【Socket网络编程】6.两个既能收也能发的udp客户端进行通信的原理

    两个既能收也能发的udp客户端进行通信的原理 ​发送数据时可能会用到INADDR_BROADCAST代表255.255.255.255的广播地址,作用范围只能在当前局域网. 接收数据可能会用到INAD ...

  9. 川崎机器人总线通信_【川崎】川崎机器人PROFINET 总线通信图文教程(上)

    本文介绍西门子 S1200/S1500 系列 PLC 通过 TIA Portal 软件平台与川崎机器人进行 PROFINET 总线通信的配制方法. 所需工具: 1. 十字螺丝刀一把(中号) 2. 1T ...

最新文章

  1. jgit查询远程仓库_JAVA 使用jgit管理git仓库
  2. java创建线程的几种方式
  3. vue导出Excel(一)
  4. springmvc与Servlet3.0不依赖common包实现文件上传
  5. (C++) CreateThread
  6. 一个aov网用邻接矩阵表示_第6章+图习题解析
  7. 文件系统:隐匿在 Linux 背后的机制
  8. AN5640摄像头模块在黑金开发板上的使用
  9. php sns 源码,ThinkSNS v4
  10. 保持简单----纪念丹尼斯•里奇(Dennis Ritchie)
  11. xdb 服务_[20200115]监听中没有xdb服务.txt
  12. 如何从虚拟机复制文件到实体机
  13. USB转串口电路之CH340G
  14. util-caleAge 计算年龄
  15. 关于算法学习的总结和感悟
  16. oracle+omf+格式,oracle omf
  17. Pycharm debug崩溃、长时间不响应 解决
  18. 陌生单词-专业英语代码编码符号2
  19. 【剖析】上拉电阻和下拉电阻原理及其作用
  20. 产品经理如何自学入门?

热门文章

  1. 异数OS 织梦师-水母(一)--消息队列篇 1
  2. ipv6抓包 tcpdump_网络抓包工具tcpdump图文教程
  3. 游戏编程模式-享元模式
  4. 华科计算机博士公寓宿舍,华中科技大学宿舍怎么样
  5. 分享Python开发的13个小游戏(附源码)
  6. C语言:模块化实现通讯录
  7. pythoncast函数用法_数据库中cast函数
  8. 开源技术 * IBM 微讲堂 | Kubeflow 系列(观看回放 | 下载讲义)
  9. 看了变形金刚的首映 ^_^
  10. vb数字转汉字大写值