Chinaunix首页 | 论坛 | 博客
  • 博客访问: 276333
  • 博文数量: 55
  • 博客积分: 1328
  • 博客等级: 中尉
  • 技术积分: 731
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-27 16:33
文章分类

全部博文(55)

文章存档

2012年(55)

分类: LINUX

2012-03-29 10:43:49

dbus提供了两 个小工具:dbus-send和 dbus-monitor。我们可以用dbus-send发送消息。用dbus-monitor监视总线上流动的消息。 让我们通过dbus-send发 送消息来调用前面的Add方法,这时dbus-send充当了应用程序B。用dbus-monitor观察调用过程中的消息。

启动example- service:

$ ./example-service

在另一个控制台启动 dbus-monitor:

$ dbus-monitor

dbus-monitor 默认监视会话总线。执行:

$ dbus-send --session --type=method_call --print-reply --dest=org.fmddlmyy.Test /TestObj org.fmddlmyy.Test.Basic.Add int32:100 int32:999

输出为:

method return sender=:1.21 -> dest=:1.22 reply_serial=2
int32 1099

dbus-monitor 的相关输出包括:

signal sender=org.freedesktop.DBus -> dest=(null destination) path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string ":1.22"
string ""
string ":1.22"
method call sender=:1.22 -> dest=org.freedesktop.DBus path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello
method call sender=:1.22 -> dest=org.fmddlmyy.Test path=/TestObj; interface=org.fmddlmyy.Test.Basic; member=Add
int32 100
int32 999
method return sender=:1.21 -> dest=:1.22 reply_serial=2
int32 1099
signal sender=org.freedesktop.DBus -> dest=(null destination) path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string ":1.22"
string ":1.22"
string ""

:1.22就是dbus-send在 本次调用中与会话总线所建立连接的唯一名。:1.21是连接“org.fmddlmyy.Test”的唯一名。 在以上输出中我们可以看到:1.22向“org.fmddlmyy.Test”发送method_call消息,调用Add方法。 :1.21通过method_return消息将调用结果发回:1.22。其它输出信息会在以后说明。

dbus-send的 详细用法可以参阅手册。调用远程方法的一般形式是:

$ dbus-send [--system | --session] --type=method_call --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值

dbus-send支 持的参数类型包括:string, int32, uint32, double, byte, boolean。

2、消息总线的方法和信 号 2.1、概述

消息总线是一个特殊的应 用,它可以在与它连接的应用之间传递消息。 可以把消息总线看作一台路由器。正是通过消息总线,D-Bus才在一对一的通信协议基础上实现了多对一和一对多的通信。

消息总线虽然有特殊的转发 功能,但消息总线也还是一个应用。 其它应用与消息总线的通信也是通过1.1节的基本消息类型完成的。作为一个应用,消息总线也提供了自己的接口,包括方法和信号。

我们可以通过向连接 “org.freedesktop.DBus ”上对象“/”发送消息来调用消息总线提供的方法。 事实上,应用程序正是通过这些方法连接到消息总线上的其它应用,完成请求公共名等工作的。

2.2、清单

消息总线对象支持第一讲中 提到的标准接口"org.freedesktop.DBus.Introspectable", 我们可以调用org.freedesktop.DBus.Introspectable.Introspect方法查看消息总线对象支持的接口。例如:

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.Introspectable.Introspect

输出为:

method return sender=org.freedesktop.DBus -> dest=:1.20 reply_serial=2
string """>














































































"

从输出可以看到会话总线对 象支持标准接口“org.freedesktop.DBus.Introspectable”和接口“org.freedesktop.DBus”。 接口“org.freedesktop.DBus”有16个方法和3个信号。下表列出了“org.freedesktop.DBus”的12个方法的简要 说明:

org.freedesktop.DBus.RequestName (in STRING name, in UINT32 flags, out UINT32 reply) 请求公众名。其中flag定义如下:
DBUS_NAME_FLAG_ALLOW_REPLACEMENT 1
DBUS_NAME_FLAG_REPLACE_EXISTING 2
DBUS_NAME_FLAG_DO_NOT_QUEUE 4

返回值reply定义如下:
DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2
DBUS_REQUEST_NAME_REPLY_EXISTS 3
DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
 
org.freedesktop.DBus.ReleaseName (in STRING name, out UINT32 reply) 释放公众名。返回值reply定义如下:
DBUS_RELEASE_NAME_REPLY_RELEASED 1
DBUS_RELEASE_NAME_REPLY_NON_EXISTENT 2
DBUS_RELEASE_NAME_REPLY_NOT_OWNER 3 
 
org.freedesktop.DBus.Hello (out STRING unique_name) 一个应用在通过消息总线向其它应用发消息前必须先调用Hello获取自己这个连接的唯一名。返回值就是连接的唯一名。 dbus没有定义专门的切断连接命令,关闭socket就是切断连接。
在1.2节的dbus-monitor输出中可以看到dbus-send调用消息总线的Hello方法。
org.freedesktop.DBus.ListNames (out ARRAY of STRING bus_names) 返回消息总线上已连接的所有连接名,包括所有公共名和唯一名。例如连接“org.fmddlmyy.Test”同时有公 共名“org.fmddlmyy.Test”和唯一名“:1.21”, 这两个名称都会被返回。
org.freedesktop.DBus.ListActivatableNames (out ARRAY of STRING bus_names) 返回所有可以启动的服务名。dbus支持按需启动服务,即根据应用程序的请求启动服务。
org.freedesktop.DBus.NameHasOwner (in STRING name, out BOOLEAN has_owner) 检查是否有连接拥有指定名称。
org.freedesktop.DBus.StartServiceByName (in STRING name, in UINT32 flags, out UINT32 ret_val) 按名称启动服务。参数flags暂未使用。返回值ret_val定义如下:
1 服务被成功启动
2 已经有连接拥有要启动的服务名
org.freedesktop.DBus.GetNameOwner (in STRING name, out STRING unique_connection_name) 返回拥有指定公众名的连接的唯一名。
org.freedesktop.DBus.GetConnectionUnixUser (in STRING connection_name, out UINT32 unix_user_id) 返回指定连接对应的服务器进程的Unix用户id。
org.freedesktop.DBus.AddMatch (in STRING rule) 为当前连接增加匹配规则。
org.freedesktop.DBus.RemoveMatch (in STRING rule) 为当前连接去掉指定匹配规则。
org.freedesktop.DBus.GetId (out STRING id) 返回消息总线的ID。这个ID在消息总线的生命期内是唯一的。

接口 “org.freedesktop.DBus”的3个信号是:

org.freedesktop.DBus.NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner) 指定名称的拥有者发生了变化。
org.freedesktop.DBus.NameLost (STRING name) 通知应用失去了指定名称的拥有权。
org.freedesktop.DBus.NameAcquired (STRING name) 通知应用获得了指定名称的拥有权。
2.3、练习

让我们来试试消息总线提供 的方法。

2.3.1、从 ListName到d-feet的基本逻辑

dbus-send调 用:

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListNames

输出为:

method return sender=org.freedesktop.DBus -> dest=:1.23 reply_serial=2
array [
string "org.freedesktop.DBus"
string "org.freedesktop.Notifications"
string "org.freedesktop.Tracker"
string "org.freedesktop.PowerManagement"
string ":1.7"
string ":1.8"
string "org.gnome.ScreenSaver"
string ":1.9"
string ":1.10"
string ":1.22"
string ":1.11"
string "org.gnome.GnomeVFS.Daemon"
string ":1.23"
string ":1.12"
string ":1.13"
string ":1.0"
string ":1.14"
string ":1.1"
string ":1.15"
string ":1.2"
string ":1.16"
string ":1.3"
string "org.gnome.GkbdConfigRegistry"
string ":1.4"
string "org.fmddlmyy.Test"
string ":1.5"
string "org.gnome.SettingsDaemon"
string ":1.6"
]

这是会话总线当前已连接的 连接名。在d-feet窗口的左侧窗口显示的就是ListNames返回的连接名。 聪明的读者也许已经想到使用消息总线的“org.freedesktop.DBus.ListNames”方法和各连接的 “org.freedesktop.DBus.Introspectable.Introspect”, 我们就可以像d-feet一样查看总线上所有连接的所有对象的所有接口的所有方法和信号。

你的想法很好。但有一个问 题,我们必须对连接中的对象调用“org.freedesktop.DBus.Introspectable.Introspect”方法。 ListNames只列出了连接名,我们怎么获取连接中的对象路径呢?

答案很简单,如果我们不知 道对象路径就从根目录开始吧。连接中的对象是按照树型结构组织的。我们遍历连接的对象树就可以找到所有的对象。 调用对象的“org.freedesktop.DBus.Introspectable.Introspect”方法就可以查看对象的所有接口的所有方法 和信号。 例如:假设我们不知道连接"org.fmddlmyy.Test"里有什么对象,我们可以对根对象"/"执行:

$ dbus-send --session --type=method_call --print-reply --dest=org.fmddlmyy.Test / org.freedesktop.DBus.Introspectable.Introspect

输出为:

method return sender=:1.22 -> dest=:1.25 reply_serial=2
string """>



"

"org.fmddlmyy.Test" 的对象树的根节点只有一个子节点"TestObj",再查看"/TestObj":

$ dbus-send --session --type=method_call --print-reply --dest=org.fmddlmyy.Test /TestObj org.freedesktop.DBus.Introspectable.Introspect

输出为:

method return sender=:1.22 -> dest=:1.26 reply_serial=2
string """>






























"

作为一个练习,让我们来查 看系统总线的上的bluez接口。执行:

$ dbus-send --system --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListNames

输出为:

method return sender=org.freedesktop.DBus -> dest=:1.30 reply_serial=2
array [
string "org.freedesktop.DBus"
string ":1.7"
string ":1.8"
string ":1.9"
string "org.freedesktop.SystemToolsBackends"
string ":1.30"
string "org.freedesktop.NetworkManagerInfo"
string ":1.20"
string "org.freedesktop.Avahi"
string ":1.21"
string "org.bluez"
string ":1.22"
string "org.freedesktop.NetworkManager"
string "org.freedesktop.ConsoleKit"
string ":1.23"
string "com.redhat.dhcp"
string ":1.13"
string ":1.0"
string ":1.14"
string ":1.1"
string ":1.15"
string ":1.2"
string "org.freedesktop.Hal"
string "com.redhat.NewPrinterNotification"
string ":1.16"
string ":1.3"
string ":1.17"
string ":1.4"
string ":1.18"
string ":1.5"
string ":1.19"
string ":1.6"
]

我们看到连 接"org.bluez"。查看它的根对象:

$ dbus-send --system --type=method_call --print-reply --dest=org.bluez / org.freedesktop.DBus.Introspectable.Introspect

输出为:

method return sender=:1.7 -> dest=:1.31 reply_serial=2
string """>



"

接着查对象"/org":

$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org org.freedesktop.DBus.Introspectable.Introspect

输出为:

method return sender=:1.7 -> dest=:1.32 reply_serial=2
string """>



"

接着查对象"/org /bluez":

$ dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez org.freedesktop.DBus.Introspectable.Introspect

输出为:

method return sender=:1.7 -> dest=:1.33 reply_serial=2
string """>










































































































"

我们看到了对象"/org /bluez"的所有接口。对象"/org/bluez"还有子节 点"service_audio"、"service_input"、"service_network"和"service_serial"。 必要时我们可以接着查下去。d-feet的基本逻辑就是这样。 后面我们会自己实现一个dteeth。dteeth是命令行程序,可以遍历指定连接的对象树,列出所有对象的所有接口的方法和信号。

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