1. 介绍

DBus是一种桌面环境的进程间通讯(IPC)机制,有低时延、低消耗等优点

基于socket,提供了一对一的对等通讯;使用dbus-daemon作为后台进程时,可实现多对多通讯

由如下三个层次
- libdbus: 接口库,提供点对点通信和数据交换的能力 
- 守护进程: 即dbus daemon进程,提供多对多的通信机制,进程与daemon建立dbus连接,由daemon进行消息的分发
- 封装库: 特定框架下的封装,如dbus-glib/GDBus, QtDBus

Tip:
在2.26版本后,GTK将dbus绑定移入GLib中
详细参考<dbus-glib和GDBus的区别>

2. 概念

2.1 总线

在DBus中,总线(bus)是一个通道,不同的程序可以通过这个通道做某些操作,比如方法调用、发送信号和监听特定的信号

在一台机器上总线守护有多个实例(instance),这些总线之间都是相互独立的

通常有两类总线

- System Bus: 供系统范围通信的系统总线, 通常只有一个(具有持久性), 常用于发送系统消息(如插入一个新的存储设备、有新的网络连接等等)
- Session Bus: 供登陆用户私有使用的会话总线

2.2 地址

每条总线都有总线地址(Address),进程通过这个地址连接到总线,总线地址形如: "/tmp/.hiddensocket"

2.3 连接

在进行IPC通信前,进程需要建立一条到总线的连接(Connection)
每个连接通常有如下两个相互映射Bus Name

- unique connection name: 由总线服务进程唯一分配, 形如":34-907"
- well-known names: 由进程请求, 形如"com.acme.PortableHole”

2.4 对象模型

2.4.1 对象

总线中信息流向的端点在D-Bus中称为对象,对象由进程创建,是进程提供服务的方式

对象的名称通常被称为对象路径(Object Path),形如"/org/kde/kspread/telcom"

对象有两类成员: 方法(Method)、信号(Signal)
方法: 一段函数代码,带有输入和输出
信号: 广播给感兴趣进程的实体,可以带有数据

每一个对象支持一个或者多个接口
接口(Interface)是一组方法和信号,定义了一个对象实体的类型
接口的命名形如: "org.freedesktop.Introspectable"

TIP: 一个进程可以创建多个对象

2.4.2 代理

总线上的对象一般通过代理(Proxy)来访问

工作方式如下:
进程A创建对象,进程B通过创建一个连接至该对象的代理,从而可以通过代理来请求对象提供的服务

是否要区分代理与对象取决于你如何使用的封装库
博主目前了解到的是在GLib中是有区分的,而在DBus原始接口中好像并没有区分

2.4.3 消息

DBus中有四类消息(Message)

 - 方法调用(method call): 将触发对象的一个method
- 方法返回(method return): 触发的method返回的结果
- 信号(signal): 通知, 可以看作为事件消息
- 错误(error): 触发的方法返回一个异常

2.5 总结

在了解了以上概念之后,我们可以理解DBus提供的访问机制如下

Address -> [Bus Name] -> Path -> Interface -> Method

3. 服务

dbus-daemon是DBus中的总线守护进程,进行消息的分发,其源码位于dbus/bus/main.c
对应于系统总线和会话总线,系统中有两个dbus-daemon进程,一个是属于system,一个是属于session(可能有多个)
这两个进程,都是由dbus-launch启动,相关工具有

dbus-send 发送消息
dbus-monitor 监视总线上的消息

环境变量DBUS_SESSION_BUS_ADDRESS的值即为dbus-daemon的总线地址

4. 使用

下面介绍了使用D-Bus low-level public API的流程

通常DBus使用中有如下通用流程

dbus_bus_get()           建立一个dbus连接, DbusConnection
dbus_bus_request_name() 为DbusConnection起别名

4.1 发送信号

建立一个dbus连接,为DbusConnection起别名
dbus_message_new_signal() 建立一个发送信号的通道,需填写该信号的接口名和信号名
- dbus_message_iter_init_append(); dbus_message_iter_append_basic() 附加相关参数
- dbus_message_append_args() 附加相关参数
dbus_connection_send(); dbus_connection_flush() 发送信号

4.2 接收信号

建立一个dbus连接,为DbusConnection起别名
dbus_bus_add_match() 为消息循环添加匹配条件(通过信号名和信号接口名)
- dbus_connection_add_filter() 定义信号接收函数
dbus_connection_read_write_dispatch() 循环调用, 该函数在收到信号时会调用上面注册的信号接收函数
消息接收函数中
dbus_message_is_signal() 判断是否为我们感兴趣的消息
dbus_message_get_args() 获取消息内容
- while(TRUE)
dbus_connection_read_write_dispatch() 进入监听循环
dbus_connection_pop_message() 从总线上取出消息
dbus_message_is_signal() 判断是否为我们感兴趣的消息
dbus_message_get_args() 获取消息内容

4.3 远程调用请求

建立一个dbus连接,为DbusConnection起别名
dbus_message_new_method_call() 申请一个远程调用通道,需要填写服务器名、接口名和方法名
dbus_message_iter_init_append(); dbus_message_iter_append_basic() 压入本次调用的参数
dbus_connection_send_with_reply() 启动发送调用并释放发送相关的消息结构
dbus_message_iter_init(); dbus_message_iter_next() 提取参数的类型和参数
dbus_message_iter_get_arg_type(); dbus_message_iter_get_basic() 也就达成了我们进行本次远程调用的目的了

4.4 远程调用监听

建立一个dbus连接,为DbusConnection起别名
while(TRUE)
dbus_connection_read_write() 进入监听循环
dbus_connection_pop_message() 从总线上取出消息
dbus_message_is_method_call()
对比消息中的方法接口名和方法名
如果一致,那么我们跳转到相应的处理中去、
在相应的处理中,我们会从消息中取出远程调用的参数。并且建立起回传结果的通路
reply_to_method_call() 回传动作本身等同于一次不需要等待结果的远程调用

参考:
<Sample>
<DBus例程>
<D-Bus学习>
<D-Bus Tutorial>
<DBus 入门与应用>
<D-Bus Specification>
<基于DBus的进程间通信(IPC)>

DBus介绍的更多相关文章

  1. CVE-2018-14424 use-after-free of disposed transient displays 分析报告

    漏洞描述 GDM守护进程不能正确的取消导出在D-Bus 接口上已经被销毁的display对象,这造成本地用户可以触发UAF,从而使系统崩溃或造成任意代码执行. 调试环境 gdm版本: 3.14.2(通 ...

  2. dbus通信与接口介绍

    DBUS是一种高级的进程间通信机制.DBUS支持进程间一对一和多对多的对等通信,在多对多的通讯时,需要后台进程的角色去分转消息,当一个进程发消息给另外一个进程时,先发消息到后台进程,再通过后台进程将信 ...

  3. DBUS及常用接口介绍

    [原文]  1. 概述 1.1  DBUS概述     DBUS是一种高级的进程间通信机制.DBUS支持进程间一对一和多对多的对等通信,在多对多的通讯时,需要后台进程的角色去分转消息,当一个进程发消息 ...

  4. RPC通信框架——RCF介绍

    现有的软件中用了大量的COM接口,导致无法跨平台,当然由于与Windows结合的太紧密,还有很多无法跨平台的地方.那么为了实现跨平台,支持Linux系统,以及后续的分布式,首要任务是去除COM接口. ...

  5. Android 4.2蓝牙介绍

    蓝牙一词源于公元十世纪丹麦国王HaraldBlatand名字中的Blatand.Blatand的英文之意就是Blue tooth.这是因为这位让丹麦人引以为傲的国王酷爱吃蓝莓以至于牙龈都被染成蓝色.由 ...

  6. android 源码目录介绍

    Android 4.0源码目录介绍|-- Makefile|-- bionic (bionic C库)|-- bootable  (启动引导相关代码)|-- build (存放系统编译规则及gener ...

  7. DBus学习笔记

    摘要:DBus作为一个轻量级的IPC被越来越多的平台接受,在MeeGo中DBus也是主要的进程间通信方式,这个笔记将从基本概念开始记录笔者学习DBus的过程 [1] DBus学习笔记一:DBus学习的 ...

  8. 第二章 Qt常用工具的介绍

    第二章 Qt常用工具的介绍 (1)No.1 qmake 相信编写过Makefile的开发人员,随着工程中源码的级数递增和以类型.功能.模块组织源码的子目录的增多,都不愿意重复机械地手工编写这个工程管理 ...

  9. 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.s ...

随机推荐

  1. Python 正则表达式 匹配任意字符

    .(句点)匹配除了换行之外的所有一个字符, .*(点-星)匹配除了换行外的所有字符 >>> >>> r=re.compile(r'.*')>>> ...

  2. 第2章 CentOS7集群环境配置

    目录 2.1 关闭防火墙 2.2 设置固定IP 2.3 修改主机名 2.4 添加用户 2.5 修改用户权限 2.6 新建目录 2.7 安装JDK 1.卸载系统自带的JDK 2.安装JDK 2.8 克隆 ...

  3. Hive如何根据表中某个字段动态分区

    使用hive储存数据时,需要对做分区,如果从kafka接收数据,将每天的数据保存一个分区(按天分区),保存分区时需要根据某个字段做动态分区,而不是傻傻的将数据写到某一个临时目录最后倒入到某一个分区,这 ...

  4. python资源大全2

    原文链接 网络 Scapy, Scapy3k: 发送,嗅探,分析和伪造网络数据包.可用作交互式包处理程序或单独作为一个库. pypcap, Pcapy, pylibpcap: 几个不同 libpcap ...

  5. MySQL之索引(二)

    高性能的索引策略 正确地创建和使用索引是实现高性能查询的基础.在MySQL之索引(一)这一章中我们介绍了各种类型的索引及其对应的优缺点.现在我们一起来看看如何真正地发挥这些索引的优势. 独立的列 我们 ...

  6. 当我们在讨论CQRS时,我们在讨论些神马?

    当我写下这个标题的时候,我就有些后悔了,题目有点大,不太好控制.但我还是打算尝试一下,通过这篇内容来说清楚CQRS模式,以及和这个模式关联的其它东西.希望我能说得清楚,你能看得明白,如果觉得不错,右下 ...

  7. day 16 JS DOM 继续

    为什么有jquey了还学DOM  ? 因为JQuey 是大而全,可能有10k 但是我们用到的只有1k  网站小没事,网站大流量就是问题 所以大网站都是自己用DOM 实现一个类似于JQuey 的适合自己 ...

  8. Analyze Program Runtime Stack

    Introduce: Process Explorer is an advanced process management utility that picks up where Task Manag ...

  9. 如何在Linux下使用Rsync

    如何在Linux下使用Rsync 吐槽 昨天对scp进行总结之后看到最后有说到Rsync,俗语有云:好奇心害死猫.抱着学习的态度将Rsync给找了出来,然后进行了一些简单的学习.下面介绍一些个常用的命 ...

  10. 12 JVM 垃圾回收(下)

    Java 虚拟机的堆划分 Java 虚拟机将堆划分为新生代和老年代.其中新生代又被划分为 Eden 区,以及两个大小相同的 Survivor 区. 默认情况下,Java 虚拟机采取一种动态分配的策略, ...