D-Bus介绍
1 D-Bus简介
D-Bus是Desktop Bus的缩写,是针对桌面环境优化的IPC(interprocess communication)机制,用于进程间的通信或进程与内核的通信。
IPC种类很多,适用的情景也不一样:CORBA 是用于面向对象编程中复杂的IPC的一个强大的解决方案。DCOP是一个较轻量级的IPC框架,功能较少,但是可以很好地集成到K桌面环境中。SOAP和XML-RPC设计用于Web 服务,因而使用HTTP作为其传输协议。D-BUS设计用于桌面应用程序和OS通信。D-Bus中D是代表桌面“Desktop”的意思,即用于桌面操作系统的通信通道。现在逐渐被引入到嵌入式系统中,不过名字还是保留原先的叫法而已。
典型的桌面都会有多个应用程序在运行,而且,它们经常需要彼此进行通信。DCOP是一个用于KDE的解决方案,但是它依赖于Qt,所以不能用于其他桌面环境之中。类似的,Bonobo是一个用于GNOME 的解决方案,但是非常笨重,因为它是基于CORBA 的。它还依赖于GObject,所以也不能用于GNOME之外。 D-BUS的目标是将DCOP和Bonobo替换为简单的IPC,并集成这两种桌面环境。由于尽可能地减少了D-BUS所需的依赖,所以其他可能会使用D-BUS的应用程序不用担心引入过多依赖。相对于其它的IPC,D-Bus丢掉了一些不必要的、复杂的东西,也正是因为这个原因,D-Bus比较快、简单。D-Bus不和低层的IPC直接竞争,比如sockets, shared memory 或者是message queues。这些低层点的IPC有它们自己的特点,和D-Bus并不冲突。
与其他重量级的进程间通信技术不同,D-Bus并未使用会话进行通信。D-Bus使用了状态以及连接的概念,使其比UDP等低级的信息传输协议更“聪明”。另一方面,它传送的是离散消息,这又与TCP协议将数据看做“流”有所不同。D-Bus支持点对点的传信,以及广播/订阅式的传信两种传信方式。
总之,D-Bus是轻量级、快速,为主流桌面环境提供统一的进程间通信界面。
2 D-Bus体系结构
D-Bus是按一定的层次结构实现的,总体上D-Bus分为三层:
Ø 底层库——libdbus,通过底层库的接口可以实现两个进程之间进行连接并发送消息。
Ø 消息通道守护进程(message bus daemon ),消息通道守护进程是基于底层库的,可以路由消息。
Ø 封装库(Wrapper libraries),将D-Bus绑定到某一通用的应用框架上,封装D-Bus底层接口为方便用户使用的通用API。
下面是对组侧D-Bus进程间通信系统的各部分的介绍。
2.1 D-Bus底层库(libdbus)
象网络套接字一样,libdbus只支持点对点的通信,即只支持一进程与另外的一个进程进行通信。通信的基于消息的,消息包含头部和消息体。
libdbus提供C语言的底层API,这些API是为D-Bus绑定到特点的对象或是语言中设计的,官方文档中建议不要在应用上直接使用底层D-Bus的底层接口。应用上使用D-Bus的绑定更方便,比如GLib绑定、Python绑定、Qt绑定和Mono绑定等。
2.2 消息通道守护进程(message bus daemon)
Bus daemon是一个特殊的进程:这个进程可以从一个进程传递消息给另外一个进程。当然了,如果有很多applications链接到这个通道上,这个 daemon进程就会把消息转发给这些链接的所有程序。在最底层,D-Bus只支持点对点的通信,一般使用本地套接字(AF_UNIX)在应用和bus daemon之间通信。D-Bus的点对点是经过bus daemon抽象过的,由bus daemon来完成寻址和发送消息,因此每个应用不必要关心要把消息发给哪个进程。D-Bus发送消息通常包含如下步骤:
Ø 创建和发送消息给后台bus daemon进程。
Ø 后台bus daemon进程会处理该消息。
Ø 目标程序接收到消息,然后根据消息的种类,做不同的响应:要么给个确认、要么应答、还有就是忽略它。
消息通道守护进程就象是一个路由器,连接到通道上的进程发送消息到通道,通道能把该消息路由到对应的一个或多个进程中去。因此在该层次上,实现了点对点通信的支持,也实现了广播/订阅通信方式。
通常消息守护进程在一个系统上有多个实例,典型的有两类实例:系统通道(system bus)和用户通道(session bus)。系统通道通常提供类似硬件变更之类消息,每个用户都有一条用户用户通道。每条用户通道仅供单独的用户使用,同时D-Bus也提供了用户权限机制供系统通道使用。
2.3 封装库(Wrapper libraries)
封装库是将libdbus的底层API绑定到特定的对象系统或是语言中,封装libdbus底层不方便在应用层使用的接口为方便用户使用的上层接口。象这类的封装库有libdbus-glib、libdbus-qt,本文档后面将就libdbus-glib上的使用进行简单介绍。
3 D-Bus术语
D-Bus中有很多术语有必要进行介绍,其中有“接口”、“对象”、“方法”等这些面向对象语言的概念,但其中的含义跟面向对象语言中的含义是不一样的。下面就对通道、地址、连接名、对象路径、对象、接口、方法和信号进行介绍。
在介绍之前,先就这些相关概念,给出一个整体的描述。正如D-Bus的体系结构中所述,D-Bus的第二层是消息通道守护进程(message bus daemon),通常一个daemon有多个实例,典型的有system bus和session bus两个实例,这里的daemon的实例就是通道。每个通道都有一个地址,应用进程就是通过这个地址和该通道进程连接的。对于通道上的每一个连接都有一个连接名对应,连接名也称bus name(很容易误会,但这里确实不是通道名,而是连接名)。每个连接上有至少一个对象,通常有多个对象,对象路径唯一标识着这个对象。对象要实现一个或多个接口,每个接口包含有若干个方法或信号。引入官方文档中的一个表格借以说明。
| A... | is identified by a(n)... | which looks like... | and is chosen by... |
| Bus | address | unix:path=/var/run/dbus/system_bus_socket | system configuration |
| Connect- ion | bus name | :34-907 (unique) or com.mycompany.TextEditor (well-known) | D-Bus (unique) or the owning program (well-known) |
| Object | path | /com/mycompany/TextFileManager | the owning program |
| Interface | interface name | org.freedesktop.Hal.Manager | the owning program |
| Member | member name | ListNames | the owning program |
3.1 通道(Bus)
在D-Bus中,通道(bus)是核心的概念:不同的程序可以通过这个通道做些操作,比如方法调用、发送信号和监听特定的信号。如前面所述通道通常有两种,系统通道(system bus)和用户通道(session bus),系统通道通常有一条,用户通道在用户登录时创建。
一条消息通道就是一个消息路由器,是消息通道守护进程(message bus daemon)的一个实例。通道在进程通信中扮演着重要的角色,但其本身也是一个进程,是一个比较特殊的进程,后面我们会介绍通道中的一些接口、方法和信号。
3.1.1 System bus
System bus是一个持久的通道,在系统启动时就创建,供系统内核和后台进程使用,具有较高的安全性。这种通道的最常用的方面就是发送系统消息,比如:插入一个新的存储设备、有新的网络连接等。
3.1.2 Session bus
Session bus是在某个用户登录后启动,属于某个用户私有,是某用户的应用程序用来通话的通道。在很多嵌入式系统中,只有一个用户ID登录运行,因此只有一个session bus,这是跟通常桌面系统中D-Bus不同的地方。
3.2 地址(Address)
每一条通道都有一个地址,进程通过这个地址连接到通道上去。连接建立有server和client,对于bus daemon,应用就是client;daemon是server。一个D-Bus的地址是指server用于监听,client用于连接的地方,例如unix:path=/tmp/abcedf标识server将在路径/tmp/abcedf的UNIX domain socket监听。地址可以是指定的TCP/IP socket或者其他在或者将在D-Bus协议中定义的传输方式。
如果使用bus daemon,libdbus将通过读取环境变量自动获取session bus damon的地址,通过检查一个指定的UNIX domain socket路径获取system bus的地址。如果使用D-bus,但不是daemon,需要定义那个应用是server,那个是client,并定义一套机制是他们认可server的地址,这样做起来很不方便,所以通常不采用。
3.3 连接名(Bus Name)
通道上的每个连接都有一个或多个名字。当连接建立以后,D-Bus 服务会分配一个不可改变的连接名,称为唯一连接名(unique connection name),这个连接名即使在进程结束后也不会再被其他进程所使用。唯一连接名以冒号开头,如:34-907″。但是这种名字总是临时分配,无法确定的,也难以记忆,因此应用可以要求有另外一个名字公共名(well-known name)来对应这个唯一标识,就像我们使用域名来对应IP地址一样。例如可以使用com.mycompany来映射:34-907。应用程序可能会要求拥有额外的周知名字公共名(well-known name)。例如,你可以写一个规范来定义一个名字叫做 com.mycompany.TextEditor。你的协议可以指定自己拥有这个名字,一个应用程序应该在路径/com/mycompany /TextFileManager下有一个支持接口org.freedesktop.FileHandler的对象。应用程序就可以发送消息到这个通道名字,对象,和接口以执行方法调用。
3.4 对象和对象路径(Object & Object Path)
这里的对象和面向对象语言中的对象含义是不同的,这里的对象表示的是D-Bus通道中信息流向的端点。对象由客户进程创建,并在连接进程中保持不变。所有使用D-BUS的应用程序都包含一些对象, 当经由一个D-BUS连接收到一条消息时,该消息是被发往一个对象而不是整个应用程序。 对象是客户进程提供服务的方式,当然客户进程可以创建多个对象。
通道的通信以对象为中心,其上的任何信息不外乎以下三类:
Ø 发送到对象上的请求;
Ø 从对象到请求进程的请求的响应;
Ø 单向的广播消息,发送到之前注册过这类消息的进程;
每条通道至少都有一个对象,这个对象代表通道本身。客户进程可以通过向这个通道对象发送请求来得到当前通道的状态。
对于底层的D-Bus协议,即libdbus API,并不理会这些na
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
