zoukankan      html  css  js  c++  java
  • DBus介绍

    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

    QQ截图20141114215855

    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)>

  • 相关阅读:
    navicat 连接 mysql 出现Client does not support authentication protocol requested by server解决方案
    oracle的concat、convert、listagg函数(字符串拼接和类型转换)
    oracle的decode、sign、nvl,case...then函数
    where、having区别
    Oracle的rollup、cube、grouping sets函数
    IP地址,子网掩码,网段表示法,默认网关,DNS服务器详解,DNS域名设计
    springmvc 参数解析绑定原理
    eclipse运行mapreduce的wordcount
    linux命令帮助 man bash
    shell学习笔记3-后台执行命令
  • 原文地址:https://www.cnblogs.com/hzl6255/p/4096260.html
Copyright © 2011-2022 走看看