D-bus学习笔记一 基础知识篇

D-Bus是GNOME和KDE环境中广泛使用的进程间通信的软件,D-Bus允许用户做方法调用或者捕获从别的程序发送的信号,从而达到进程通信的目的。

Dbus 使用指南

1.D-Bus 是什么?

  • d-bus 是类unix 操作系统IPC 机制
  • 可用于系统通知,桌面交互操作
  • 低开销:使用二进制协议,需要类似XML
    文本格式转换
  • 易使用:使用 message 来通讯,开发者可
    利用d-bus动态库使用d-bus已有的
    object/type 系统开发

1.2D-Bus 类型

  • system bus
    系统更新通知,如插入新设备通知、新软件安装通知等
  • session bus
    桌面应用的交互协作能力,可以作为文件系统监控器和配置服务器

D-Bus 协议

简介
消息协议由 首部( header ) 和 主体( body ) 两部分组成。

header 的签名是固定的,值的含义也是固定的
header 的长度必须是8的整数倍,以便数据进行对齐
body 只有值,其签名在 header 中
body 的长度不需要为8的倍数
header 加 body 的总长度(包括对齐充填)不得超过128MiB
首部

header 的类型签名为 yyyyuua(yv) ,即 :

byte, byte, byte, byte, uint32, uint32, struct{byte, variant}[] 

这些值具有以下含义

说明
第一个byte字节序,'l’表示小端、'B’表示大端
第二个byte消息类型
第三个byte位标志的按位或
第四个byte协议版本,只能为1
第一个uint32主体的长度(以字节为单位)
第二个uint32消息的序列号
结构体数组首部字段数组,byte是字段标识,varaint是字段的值
  • 消息类型
类型说明
INVALID0无效的类型,必须被忽略
METHOD_CALL1方法调用
METHOD_RETURN2方法调用的返回值
ERROR3错误回复
SIGNAL4信号发送

位标志

标志说明

NO_REPLY_EXPECTED | 0x01 |不需要返回值和错误
NO_AUTO_START| 0x02| 不自动启动接收方进程
ALLOW_INTERACTIVE_AUTHORIZATION 0x04 通知接收方调用者已准备好等待交互式授权,仅当非特权代码调用特权更大的方法,并且部署了允许进行交互式授权的授权框架时,此标志才有效。

  • 首部字段
字段名字段标识字段值类型何时必填说明
INVALID0N/AN/A无效
PATH1OBJECT_PATHMETHOD_CALL, SIGNAL对象路径
INTERFACE2STRINGSIGNAL被调用的接口或触发点信号
MEMBER3STRINGMETHOD_CALL, SIGNAL方法或信号的名称
ERROR_NAME4STRINGERROR发生的错误的名称
REPLY_SERIAL5UINT32ERROR, METHOD_RETURN答复的消息的序列号
DESTINATION6STRING非必填此消息打算连接的目标的名称
SENDER7STRING非必填发送方的唯一名称
SIGNATURE8SIGNATURE非必填body 的类型签名
UNIX_FDS9UINT32非必填带外数据中文件描述符的个数

主体
首部中已经确定了目标,且主体部分的类型签名也在首部字段的SIGNATURE中,因此主体只需要按照 封装格式封装数据即可。

例如调用 org.demo.Hbc.Speak(string msg) 方法,对象路径为 /org/demo/Hbc ,参数为 “hello world” ,不需要返回值,则整个消息如下(假设采用小端字节序):

// header 
0x6c 0x01 0x01 0x01 // 'l' + METHOD_CALL +   NO_REPLY_EXPECTED + 协议版本1 
0x0f 0x00 0x00 0x00 // body长度为15字节 
0x01 0x00 0x00 0x00 // 消息的序列号 
0x01 0x00 0x00 0x00 // PATH的字段标识 + 充填0 
0x0d 0x00 0x00 0x00 // string的长度为13 
0x2f 0x6f 0x72 0x67 // "/org" 
0x2f 0x64 0x65 0x6d // "/dem" 
0x6f 0x2f 0x48 0x62 // " o/ Hb" 
0x63 0x00 0x00 0x00 // "c" + 结尾0 + 充填0 
0x02 0x00 0x00 0x00 // INTERFACE的字段标识 + 充填0 
0x12 0x00 0x00 0x00 // string的长度为18 
0x6f 0x72 0x67 0x2e // "org." 
0x64 0x65 0x6d 0x6f // "demo" 
0x2e 0x48 0x62 0x63 // ".Hbc" 
0x2e 0x53 0x70 0x65 // ".Spe" 
0x61 0x6b 0x00 0x00 // "ak" + 结尾0 + 充填0 
0x03 0x00 0x00 0x00 // MEMBER的字段标识 + 充填0 
0x05 0x00 0x00 0x00 // string的长度为5 
0x53 0x70 0x65 0x61 // "Spea" 
0x6b 0x00 0x00 0x00 // "k" + 结尾0 + 充填0 
0x06 0x00 0x00 0x00 // DESTINATION的字段标识 + 充填0 
0x04 0x00 0x00 0x00 // string的长度为4 
0x3a 0x31 0x2e 0x30 // ":1.0" 这是假设的 
0x00 0x00 0x00 0x00 // 结尾0 + 充填0 
0x08 0x00 0x00 0x00 // SIGNATURE的字段标识 + 充填0 
0x01 0x73 0x00 0x00 // signature的长度为1,值为"s" + 结尾0 + 充填0 

// body 
0x0b 0x00 0x00 0x00 // String长度为11字节 
0x68 0x65 0x6c 0x6c // "hell" 
0x6f 0x20 0x77 0x6f // "o wo" 
0x72 0x6c 0x64 0x00 // "rld" + 结尾0 

1.3 D-Bus 体系介绍

D-Bus是一套进程通信体系,它有以下几层:
1.libdbus库,提供给各个应用程序调用,使应用程序具有通信和数据交换的
能力,两个应用程序可以直接进行通信,就像是一条socket通道,两
个程序之间建立通道之后,就可以通讯了。
2.消息守护进程,在libdbus的基础上创建,可以管理多个应用程序之间的通
信。每个应用程序都和消息守护进程建立dbus的链接,然后由消息守
护进程进行消息的分派。
3.各种包装库,有libdbus-glib,libdbus-qt等等,目的是将dbus的底层api进
行一下封装。

2. D-Bus怎么用?

流程:

关键的接口以及功能:

DBusConnection *dbus_bus_get (DBusBusType type, DBusError *error) /* 建立和总线的连接 */

int dbus_bus_request_name (DBusConnection *connection,
const char *name,
unsigned int flags,
DBusError *error) /* 注册连接名称 */

DBusMessage *dbus_message_new_signal (const char *path,
const char *iface,
const char *name) /* 创建信号类型消息*/

void dbus_message_iter_init_append ( DBusMessage *message,
DBusMessageIter *iter) /* 加入参数到信号 */

dbus_bool_t dbus_connection_send ( DBusConnection *connection,
DBusMessage *message,
dbus_uint32_t *serial) /* 发送信号到总线 */

void dbus_message_unref (DBusMessage *message) /* 释放消息 */

void dbus_bus_add_match ( DBusConnection *connection,
const char *rule,
DBusError *error) /* 请求获取调用消息 */

DBusMessage *dbus_connection_pop_message ( DBusConnection *connection) /* 从总线获取消息 */

dbus_bool_t dbus_message_is_method_call (DBusMessage *message,
const char *iface,
const char *method) /* 判定消息是方法调用 */

dbus_bool_t dbus_message_iter_init (DBusMessage *message,
DBusMessageIter *iter) /* 获取参数 */

DBusMessage *dbus_message_new_method_return (DBusMessage *method_call) /* 创建返回消息 */

void dbus_message_iter_init_append ( DBusMessage *message,
DBusMessageIter *iter) /* 在消息中填入参数 */

dbus_bool_t dbus_connection_send ( DBusConnection *connection,
DBusMessage *message,
dbus_uint32_t *serial) /* 发送返回消息 */

DBusMessage *dbus_message_new_method_call (const char *destination,
const char *path,
const char *iface,
const char *method) /* 创建一个函数调用消息 */

void dbus_message_iter_init_append (DBusMessage *message,
DBusMessageIter *iter) /* 为消息添加参数 */

dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection,
DBusMessage *message,
DBusPendingCall **pending_return,
int timeout_milliseconds) /* 发送消息 */

void dbus_pending_call_block (DBusPendingCall *pending) /* 阻塞等待返回值 */

DBusMessage *dbus_pending_call_steal_reply (DBusPendingCall *pending) /* 获得返回消息 */

dbus_bool_t dbus_message_iter_init (DBusMessage *message,




2.D-Bus相关工具

d-feet dbus-sender dbus-mointer

1.dbus-send 可以进行信号的发送

Usage: dbus-send [--help] [--system | --session | --bus=ADDRESS | --peer=ADDRESS] 
[--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]

命令参数说明:

--dest:指定接收消息的连接名称

--print-reply:阻止对已发送消息的答复,打印收到的所有答复。消息类型--type = method_call。

--print-reply=literal:阻止对已发送消息的答复,并打印答复内容,如果答复是对象路径或字符串,则按原样打印,没有标点,转义字符等。

--reply-timeout:等待答复最大毫秒值,默认25秒

--system和--session:系统总线和会话总线,默认会话总线

--bus:在指定的消息总线上注册,通常是dbus-daemon

--peer:发送非DBus消息到指定的DBus服务上,dbus-send将不会调用Hello方法

--sender:发送消息之前,给发送者授权, 退出时,释放该发送者

--type:指定method_call或signal(默认为“ signal”)

案例:

用例形式是:
           dbus-send --dest=org.freedesktop.ExampleName               \
                       /org/freedesktop/sample/object/name              \
                       org.freedesktop.ExampleInterface.ExampleMethod   \
                       int32:47 string:'hello world' double:65.32       \
                       array:string:"1st item","next item","last item"  \
                       dict:string:int32:"one",1,"two",2,"three",3      \
                       variant:int32:-8                                 \
                       objpath:/org/freedesktop/sample/object/name

其中:

–system ##将命令发向系统总线,也可使用–session
–print-reply ## 打印返回结果
–dest=org.freedesktop.ExampleName ##服务名。用户可以用查询命令获得当前系统的所有服务名
/org/freedesktop/sample/object/name ## 对象名。由服务定义
org.bluez.audio.Manager.CreateDevice
org.freedesktop.ExampleInterface.ExampleMethod ##方法名
int32:47 string:‘hello world’ double:65.32
array:string:“1st item”,“next item”,“last item”
dict:string:int32:“one”,1,“two”,2,“three”,3
variant:int32:-8
objpath:/org/freedesktop/sample/object/name ## 参数 类型:值 int32:123



  dbus-send的详细用法可以参阅手册($man dbus-send或者$dbus-send --help)。


2. d-feet 查看内核接口

当你准备使用D-Bus实现你的通信功能,D-Feet会很方便:它可以显示service提供的所有对象、信号、和方法。另外还可以通过它实现方法调用。

 

1. dbus-monitor
使用手册
dbus-monitor 具有两种不同的文本输出模式:“经典”风格的监视模式和配置文件模式

配置文件模式:一种紧凑格式,每条消息只有一行,并且具有微秒分辨率的定时信息

dbus-monitor 也有两种特殊的二进制输出模式:–binary 和–pcap

--binary:二进制模式将输出整个二进制消息流
--pcap:将PCAP文件头添加到输出的开头,并为每个消息添加PCAP消息头
如果未指定任何模式,则 dbus-monitor 将使用监视输出格式。

--system 和 --session表示系统总线和会话总线,默认为--session
--address ADDRESS:监视在ADDRESS处给定的任意消息总线
--profile:使用配置文件模式打印
--monitor:使用dbus-monitor模式打印
输出概要:

type:分为signal和method_call
sender:消息或方法调用者
dest:消息接收或方法拥有者
interface:接口名
path:服务路径
member:方法名或属性名
replay:方法调用的返回值
监视某些系统级接口时,需要加上 sudo 权限,如监视 lastore 更新模块 sudo dbus-monitor --system "interface=com.deepin.lastore.Manager"

监视信号

dbus-monitor type=‘signal’,sender=‘org.gnome.TypingMonitor’,interface=‘org.gnome.TypingMonitor’


监视方法

dbus-monitor --session “interface=com.deepin.daemon.Display”





## 3.D-Bus 需要注意的问题?
todo


[dbus 信号收发小例子](https://blog.csdn.net/wuquan_1230/article/details/87934203?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1.pc_relevant_paycolumn_v3&spm=1001.2101.3001.4242.2&utm_relevant_index=4)

[dbus 官方文档](http://www.freedesktop.org/software/dbus/
)



* [dbus-send](https://blog.csdn.net/machiner1/article/details/44936519/)

* [协议](https://dbus.freedesktop.org/doc/dbus-specification.html#stability)
* [D-Bus体系](http://blog.chinaunix.net/uid-28584979-id-5050928.html)

* [busctl 中文手册](http://www.jinbuguo.com/systemd/busctl.html)

简单实用
* [dbus 应用案例 ****](https://blog.csdn.net/eydwyz/article/details/70175289?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1.no_search_link&spm=1001.2101.3001.4242.2)


* [dbus 学习链接 **** 通俗易懂](http://www.fmddlmyy.cn/mytext.html)
* 


go dbus 案例
[godbus 学习资料 比较全面](https://pkg.go.dev/github.com/godbus/dbus/v5)

[go dbus 应用](https://www.codeplayer.org/Wiki/go/%E5%9C%A8go%E4%B8%AD%E4%BD%BF%E7%94%A8dbus%E5%92%8Cgsettings.html#org21a125a)


  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值