Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3519445
  • 博文数量: 1805
  • 博客积分: 135
  • 博客等级: 入伍新兵
  • 技术积分: 3345
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-19 20:01
文章分类

全部博文(1805)

文章存档

2017年(19)

2016年(80)

2015年(341)

2014年(438)

2013年(349)

2012年(332)

2011年(248)

分类: LINUX

2016-06-28 08:43:11

原文地址:DBus 介绍 作者:wangchenxicool

    dbus是freedesktop下开源的Linux IPC通信机制,本身Linux 的IPC通信机制包括,管道(fifo),共享内存,信号量,消息队列,Socket等。 像现在流行的moblin平台就使用了DBUS通信,还有我最近看的bluez 4 也是通过DBUS来交互的。
 
      它是个3层架构的进程间通信系统,包括:   

            1.   函数库libdbus,用于两个应用程序呼叫联系和交互消息。

            2.   Message bus daemon,总线守护进程可同时与多个应用程序相连,并能把来自一个应用程序的消息路由到0或者多个其他程序。

            3.   一系列基于特定应用程序框架的Wrapper库。 比如libdbus-glib, libdbus-python.

      参看图1-1,  Bus Daemon Process就是运行在linux的daemon(dbus-daemon, 用户可以在/etc/init.d/dbus 操作,stop, start等等),  dbus-daemon运行时会调用libdus的库。 在Application Process1里面就是应用层的东西了,应用程序调用特定的应用程序框架的Wrapper库与dbus-daemon进行通信。

      我前段时间就是用Python写程序与dbus-daemon通信,所以就需要libdbus-python,后来又用c写程序,又装了libdus-glib。实质上在dbus主页上()提供了很多Wrapper库, for QT4, JAVA, Perl, C++, Pascal, QT3, .NET, Ruby等等。这个Wrapper库呢其实就是对dbus下层调用做了封装,给上层暴露一个友好的接口。dbus的底层其实也是通过socket通信的

                                                                         图 1-1    
      我再给一张bluez的例子让大家更理解dbus; 有四个应用想与bluz的damon通信,bluez注册到dbus中,其它的应用只需要向dbus要bluez的数据,
dbus负责再和bluez沟通了,但是bluez一定要把接口告诉其它应用。


      理解有限,先说到这。
 
 
 
 
 

D-Bus 指南

什么是D-Bus?

D-Bus是一套进程间通信(IPC)系统。从结构上讲,它包括几个层次:

  • 一个库,libdbus,它允许两个应用程序相互连接并交换信息。
  • 一个消息总线守护进程的可执行文件,基于libdbus,多个应用程序可以连接其上。守护进程可以将一个应用程序的消息路由到零个或多个其他应用程序。
  • 封装库或基于某个特定应用程序框架的绑定,例如,libdbus-glib和libdbus-qt。还有一些语言如Python的绑定。大多数人都应该使用这些封装库的API,因为它们简化了D-Bus编程细节。libdbus被有意设计成为更高层次绑定的后端。大部分libdbus的API仅仅是为了用来实现绑定。

libdbus只支持一对一的连接,类似于一个原始的网络套接字。不过,你在连接上发送的不是字节流,而是消息。消息包括一个用来识别消息类型的消息头,和一个包含数据包的消息体。libdbus还抽象了具体的传输过程(套接字或其他方式),并且处理一些诸如认证之类的具体事务。

消息总线守护进程就像一个轮子的轮毂。轮子的每一条轮辐都通过libdbus一对一的连接到应用程序。应用程序通过轮辐发送消息给总线守护进程,总线守护进程再将消息转发给连接其上的相应的应用程序。可以把守护进程想象成一个路由器。

在典型的计算机中总线守护进程有多个实例。第一个实例是一个全局的单实例,一个类似sendmail或Apache的系统守护进程。这个实例对接收何种消息有严格的安全限制,并且被用作整个系统内的通信。其他的实例是每个用户登录会话创建一个。这些实例允许用户会话的应用程序间相互通信。

系统的和用户的守护进程都是相对独立的。一般会话内的IPC不会涉及整个系统的消息总线进程,反之亦然。

D-Bus应用

D-Bus专为两种具体情况设计:

  • 同一桌面会话的应用间的通信,以允许整合桌面会话成为一个整体,并解决进程的生命周期(桌面组件什么时候开始和停止运行)问题。
  • 桌面会话和操作系统间的通信,操作系统通常包括内核和任何系统守护进程或进程。

就内置桌面会话而言,GNOME和KDE桌面有着截然不同的IPC解决方案经验,如CORBA和DCOP。D-Bus的建立基于这些经验,并且精心设计,以满足这些桌面应用的特殊需求。D-Bus可能适合也可能不适合其他应用。

D-Bus可能偶尔也会有除了设计目的以外的其他用途。它区别于其他形式的IPC的特性包括:

  • 用于异步的二进制协议设计(本质上类似于X Window System协议)。
  • 始终打开的,稳定的,可靠的连接。
  • 消息总线是一个守护进程,而不是一个“集群”或分布式构架。
  • 指明了许多实施和部署问题,而不是模糊的/可配置/可拔插的。
  • 语义上类似于现存的DCOP系统,使得KDE更容易接受它。
  • 用来支持系统消息总线模式的安全功能。

基本概念

一些无论你用什么应用程序框架编写D-Bus应用都需要的基本概念。实际的GLib或Qt或Python应用程序代码会有所不同。

diagram

本地对象和对象路径

你的编程框架可能定义了“对象”是什么样的,通常是一个基类。例如:java.lang.Object, GObject,QObject,python’s base Object,或任何其他形式。 让我们称之为本地对象

低层次D-Bus协议,以及相应的libdbus API,不关心本地对象。然而,它提供了一个称之为对象路径的概念。对象路径的想法是,更高层次的绑定可以命名本地对象的实例,并允许远程应用程序引用它们。

对象路径看起来像一个文件系统路径,例如一个对象可以命名为/org/kde/kspread/sheets/3/cells/4/5。人类可读的路径是较好的,但你也可以创建一个对象名为/com/mycompany/c5yo817y0c1y1c5b如果它对您的应用程序有意义的话。

对象路径的命名空间是比较巧妙,只需在开头加上你自己的域名(如:/org/kde)。这将保持同一进程中的不同代码模块互不干扰。

方法和信号

每个对象都有成员;成员有两种类型,方法信号。方法是一类可以在对象中被调用的操作,具有可选的输入(亦称参数或“入参”)和输出(亦称返回值或“出参”)。信号是对象发给任何感兴趣的观察者的广播;信号可能包含一个数据包。

方法和信号都通过名字被引用,如“Frobate”或“OnClicked”。

接口

每个对象都支持一个或多个接口。可以把接口想象成被命名的一组方法和信号,就像它在GLib或Qt或Java中一样。接口定义了一个接口对象实例的类型。

D-Bus通过一个简单的命名空间字符串来识别接口,如org.freedesktop.Introspectable。大多数绑定会直接映射这些接口名字到相应的编程语言结构,如Java的接口或C++的纯虚类。

代理

一个代理对象是一个用来代表另一个进程中的远程对象的合适的本地对象。低层次的D-Bus API包括手动的创建一个方法调用消息,发送,然后手动的接收和处理方法的回复消息。更高层次的绑定提供代理作为替代。代理看起来像一个普通的本地对象;但是当你调用一个代理对象的方法,绑定会将它转换成一个D-Bus的方法调用消息,等待回复消息,解包回复消息,并从本地方法中返回。

不使用代理的程序伪代码:

          Message message = new Message("/remote/object/path", "MethodName", arg1, arg2);
          Connection connection = getBusConnection();
          connection.send(message);
          Message reply = connection.waitForReply(message);
          if (reply.isError()) {

          } else {
             Object returnValue = reply.getReturnValue();
          }

使用代理后:

          Proxy proxy = new Proxy(getBusConnection(), "/remote/object/path");
          Object returnValue = proxy.MethodName(arg1, arg2);

总线名字

当每个应用程序连接到总线守护进程时,守护立即赋予它一个名字,称做唯一的连接名字。唯一的名字以一个‘:’(冒号)字符开头。这些名字在总线守护进程的生命周期中不会被重用——也就是说,你知道的一个给定的名字永远指向同一个应用。一个唯一名字的例子:34-907。冒号后面的数字除了唯一性以外没有任何意义。

当一个名字被映射到特定的应用程序的连接,该应用程序就说自己拥有这个名字。

应用程序可能会要求拥有额外的周知名字。例如,你可以写一个规范来定义一个名字叫做com.mycompany.TextEditor。你的协议可以指定自己拥有这个名字,一个应用程序应该在路径/com/mycompany/TextFileManager下有一个支持接口org.freedesktop.FileHandler的对象。

应用程序就可以发送消息到这个总线名字,对象,和接口以执行方法调用。

你可以把唯一名字比作IP地址,而把周知名字比作域名。所以,就像mycompany.com映射到192.168.0.5一样,com.mycompany.TextEditor可能映射到:34-907。

除了路由消息,名字还有第二重要的用途。它们被用来跟踪的生命周期。当一个应用程序退出(或奔溃),它到消息总线的连接会被操作系统关闭。消息总线随后发出通知消息告诉其余应用程序,这个应用程序的名字失去了他的拥有者。通过跟踪这些通知,你应用程序就可以可靠地监控其他应用程序的生命周期。

总线名字也可用于协调单实例应用。例如如果你想确保只有一个com.mycompany.TextEditor应用运行,只需让文本编辑器退出,如果发现总线名字已经有一个拥有者。

地址

使用D-Bus的应用程序可以是服务器或客户端。服务器侦听传入的连接;客户端连接到服务器。一旦连接建立起来,它就是一个对等的消息流,客户端和服务器只在建立连接时区分。

如果你可能使用总线守护进程,你的应用程序将是总线守护进程的一个客户端。也就是说,总线守护进程监听连接,你的应用程序初始化一个到总线守护进程的连接。

D-Bus地址指定了服务器监听哪和客户端连接到哪。例如,地址unix:path=/tmp/abcdef指定服务器将在UNIX域套接字的路径/tmp/abcdef下侦听,并且客户端将连接到这个套接字。地址也可以指定TCP/IP套接字,或将来的D-Bus升级规范中定义的任何传输协议。

大概念图

消息——后台

调用方法——后台

促发信号——后台

反思

阅读(1300) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~