0%

浅谈dbus

前言

最近项目上面要在两个进程间通信,传递一些设置的信息。而且之前项目调用系统的一些接口使用了dbus的通信机制,所以想着也使用dbus来做这个功能。

概要

D-Bus是一个低开销,易使用的IPC系统。 协议传递的是二进制数据, 而不是其他的文本格式(如JSON/XML), 协议是基于消息处理的, 而不是基于流。根据名字可以看出,这是一个总线型的通信机制,所有节点挂载总线上,节点发送消息到总线上,根据消息的头部信息定位目标节点,基于消息总线转发各个应用间的消息。

dbus在linux桌面会话间用的相当广泛,已经是一个成熟的系统了。

消息总线分为两种类型:

  • system, 用于系统与用户会话的通知, 允许系统从用户会话中获取输入,系统中只允许存在一个系统总线
  • session, 用于实现 desktop environment, 例如: GNOME, KDE,系统中可以存在多个session总线

D-Bus不是设计被用于任何应用间的交互, 缺少许多其他IPC方式的特性。 D-Bus daemon也提供了许多其他IPC没有的特性, 例如 Bus-name, 用于服务启动和安全策略。

术语

bus name: 每个应用连接到总线上,每个连接都通过一个bus name来标识。消息发送的时候,指定目标bus name, 总线就知道转发给哪个应用了。

对象: 每个应用可以提供多个对象,对象就是一组接口的抽象,提供给其他应用定位接口的。

路径: 每个对象对应的有一个路径,用于定位对象的。消息发送的时候,也会指定路径,表示要调用应用的哪个对象下的哪个接口。

接口: 接口就是具体调用的方法了。接口包含在对象中, 不同的对象可以提供同名的方法,但是实现可以不同,包括类型啊, 参数、返回值等都可以不一样,其实就是不同的接口。 接口有两种类型, 分别为方法和信号。 方法是提供给应用精确调用的,方法属于单播的消息,传递参数,返回执行结果。信号的发送是一个广播的消息,应用要处理什么信号,可以增加一个过滤器,告诉总线我想接收什么信号,信号不需要返回值,只需要处理就行了。

地址:系统上面可以运行多个总线,只有挂载到同一个总线上面的应用才可以相互通信。总线通过地址来区分,应用建立连接的时候需要指定总线的地址,这个总线的地址是存在环境变量DBUS_SESSION_BUS_ADDRESSDBUS_SYSTEM_BUS_ADDRESS中的。系统默认会起一个system类型的总线,如果是界面登陆的终端,默认有一个session类型的总线,但如果是ssh或者Telnet连接的终端,就没有session总线了。 总线是通过一个后台daemon运行的。

inspect: 对象接口的xml声明,用于告知客户端dbus-name对应的应用提供了什么样的对象,路径是什么,接口是什么,还有就是接口的入参、出参的类型。只有实现了返回inspect的接口,才可以通过d-feet查看到具体的信息。

类型系统: dbus有一个类型系统,表示了ASCII码到具体数据类型的映射。用于对数据封包解包。

交互模型

这是个网络上的图片,详细的描述了dbus的通信流程。

avatar

server代码流程

avatar

client代码流程

avatar

调试

dbus自身提供了dbus-monitor, dbus-send等程序用于调试。

Ubuntu里面还可以安装d-feet程序,对dbus用一个可视化的了解。

参考资料

这些是我在学习的过程中,看到的比较好的一些资料, 讲的比较详细。

官方文档

博客
http://www.fmddlmyy.cn/mytext.html 全局了解
https://www.cnblogs.com/chenbin7/archive/2013/03/05/2944895.html api使用

dbus-next文档
https://python-dbus-next.readthedocs.io/en/latest/high-level-service/index.html 这个是python的库,属于dbus的高度封装库,使用比较简便。

样例代码

https://github.com/fishmwei/dbus-demo

行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。