研究BlueZ就必须得理解D-Bus,移植BlueZ的很多Bug就是因为不同版本BlueZ的D-Bus接口不一致造成的。本来想通过翻译强制自己仔细阅读这个D-Bus Tutorial (http://dbus.freedesktop.org/doc/dbus-tutorial.html)。翻译到半截,却发现有人已经搞定了,只是搜索起来比较费劲而已。保留自己的部分成果,然后再转贴没有校正过的。
Havoc Pennington Red Hat, Inc. <[email protected]>
David Wheeler
John Palmieri
Red Hat, Inc.
<[email protected]>
Colin Walters
Red Hat, Inc.
<[email protected]>
Version 0.5.0
This tutorial is not complete; it probably contains some useful information, but also has plenty of gaps. Right now, you’ll also need to refer to the D-Bus specification, Doxygen reference documentation, and look at some examples of how other apps use D-Bus.
Enhancing the tutorial is definitely encouraged – send your patches or suggestions to the mailing list. If you create a D-Bus binding, please add a section to the tutorial for your binding, if only a short section with a couple of examples.
D-BUS 是一种进程间通信的方式,从架构上来说,分为三层:
libdbus仅支持一对一的连接,就像原始 socket通讯方式一样。但它传递的不是以字节为单位的数据流,而是具有一定意义的消息包。消息的消息头部表示消息种类,消息体用来装载数据。 Libdbus也可以允许实现特定的传输通道,从而来完成比如像认证之类的应用细节(libdbus also abstracts the exact transport used (sockets vs. whatever else), and handles details such as authentication.)。
消息总线守护进程将D-bus上连接的所有程序构成一个轮形hub。Libdbus为中心,它和应用程序建立一对一的连接。每个应用程序通过通道发送消息到消息总线,然后总线进程将消息转发到其他连接到hub的应用程序。可以把消息总线理解为一个路由器。
Dbus服务在一个操作系统中存在多个进程。第一个进程是一个全局进程,就如sendmail 或Apache 的系统守护进程一样。这个进程具有高度的安全限制,一般用于系统进程间的通讯。其他的dbus进程都是用户进程,针对于每个登录的用户建立。这些实例允许 用户会话中的应用程序相互通信。
Dbus全局进程和用户进程是相互独立的,他们并没有内在的依赖关系。
有很多种IPC或者网络通信系统,如:CORBA, DCE, DCOM, DCOP, XML-RPC, SOAP, MBUS, Internet Communications Engine (ICE)等等,可能会有数百种,dbus的目的主要是下面两点:
(有省略)
D-Bus的采用能够解决比如像系统热插拔消息向用户程序通知的问题。
D-Bus may happen to be useful for purposes other than the one it was designed for. Its general properties that distinguish it from other forms of IPC are:
在不同的编程语言中,都定义了一些“对象”,如java中的java.lang.Object,GLIB中的GObject,QT中的QObject等等。这些我们都可以叫做“原始对象”(native object)。
D-BUS的底层接口,和libdbus API相关,是没有这些对象的概念的,它提供的是一种叫对象路径(object path),用于让高层接口绑定到各个对象中去,允许远端应用程序指向它们。
object path就像是一个文件路径,可以叫做/org/kde/kspread/sheets/3/cells/4/5等。路径中间的标识符可以是有意义的,也可以直接是无意义的字符串。
将对象用名字空间来区分,这解决了命名冲突的问题。
每个对象都有一些成员,有两种成员:方法(methods)和信号(signals),在对象中,方法可以被调用。信号会被广播,感兴趣的对象可以处理这个信号,同时信号中也可以带有相关的数据。
每一个方法或者信号都可以用一个名字来命名,如”Frobate” 或者 “OnClicked”。
每个对象都有一个或者多个接口,一个接口就是多个方法和信号的集合。这个概念和Glib, Qt或者Java中的是一致的。接口定义了对象实例的类型。
dbus使用简单的命名空间字符串来表示接口,如org.freedesktop.Introspectable。可以说dbus接口相当于C++中的纯虚类。
使用代理对象就是让调用者感觉在直接使用远程对象一样。d-bus的底层接口完成了一些比较低级和繁琐的调用过程,比如必须先调用创建方法形成消息 包,然后发送,然后等待接受和处理返回的消息。所以,高层的接口就可以使用代理对象提供的接口屏蔽这些细节。所以,当调用代理对象的方法时,代理内部会转 换成dbus的方法调用,等待消息返回,对返回结果解包,返回给相应的方法。可以看看下面的例子,使用dbus底层接口编写的代码:
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);
客户端代码减少很多。
当一个应用程序连接上bus daemon时,daemon会分配一个唯一的名字给它。以冒号(:)开始,这些名字在daemon的生命周期中是不会改变的,可以认为这些名字就是一个 IP地址。当这个名字映射到应用程序的连接上时,应用程序可以说拥有这个名字。同时应用可以声明额外的容易理解的名字,比如可以取一个名字 com.mycompany.TextEditor,可以认为这些名字就是一个域名。其他应用程序可以往这个名字发送消息,执行各种方法。
名字还有第二个重要的用途,可以用于跟踪应用程序的生命周期。当应用退出(或者崩溃)时,与bus的连接将被OS内核关掉,bus将会发送通知,告诉剩余的应用程序,该程序已经丢失了它的名字。
名字还可以检测应用是否已经启动,这可以用来实现单实例启动程序。
使用d-bus的应用程序既可以是server也可以是client,server监听到来的连接,client连接到server,一旦连接建 立,消息就可以流转。如果使用dbus daemon,所有的应用程序都是client,daemon监听所有的连接,应用程序初始化连接到daemon。
dbus地址指明server将要监听的地方,client将要连接的地方,例如,地址:unix:path=/tmp/abcdef表明 server将在/tmp/abcdef路径下监听unix域的socket,client也将连接到这个socket。一个地址也可以指明是TCP /IP的socket,或者是其他的。
当使用bus daemon时,libdbus会从环境变量中(DBUS_SESSION_BUS_ADDRESS)自动认识“会话daemon”的地址。如果是系统 daemon,它会检查指定的socket路径获得地址,也可以使用环境变量(DBUS_SESSION_BUS_ADDRESS)进行设定。
当dbus中不使用daemon时,需要定义哪一个应用是server,哪一个应用是client,同时要指明server的地址,这不是很通常的做法。
将上面的概念综合起来,如果要在指定的对象中调用指定的方法,则需要知道如下的参数:
Address -> [Bus Name] -> Path -> Interface -> Method
bus name是可选的,除非是希望把消息送到特定的应用中才需要。
interface也是可选的,有一些历史原因,DCOP不需要指定接口,因为DCOP在同一个对象中禁止同名的方法。所以D-Bus允许你忽略接口参数,但如果方法名字有歧义,那么行为不可预料。
其他请参考链接:http://blog.robotercoding.com/?cat=6