2、D-Bus的基本概念
2.1、从例子开始
./autogen.sh ./configure make
./example-service
2.2、名词
2.2.1、Bus Name
2.2.1.1、可能有多个备选连接的公共名
2.2.1.2、每个连接都有一个唯一名
2.2.2、Object Paths
2.2.3、Interfaces
- org.fmddlmyy.Test.Basic
- org.freedesktop.DBus.Introspectable
- org.freedesktop.DBus.Properties
2.2.4、Methods和Signals
2.3 小结
3 下集预告
1、D-Bus的消息
1.1、消息类型
- method_call 方法调用
- method_return 方法返回
- error 错误
- signal 信号
1.2、dbus-send和dbus-monitor
$ ./example-service
$ 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
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 ""
$ dbus-send [--system | --session] --type=method_call --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值
2、消息总线的方法和信号
2.1、概述
2.2、清单
$ 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 "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg name="data" direction="out" type="s"/> </method> </interface> <interface name="org.freedesktop.DBus"> <method name="Hello"> <arg direction="out" type="s"/> </method> <method name="RequestName"> <arg direction="in" type="s"/> <arg direction="in" type="u"/> <arg direction="out" type="u"/> </method> <method name="ReleaseName"> <arg direction="in" type="s"/> <arg direction="out" type="u"/> </method> <method name="StartServiceByName"> <arg direction="in" type="s"/> <arg direction="in" type="u"/> <arg direction="out" type="u"/> </method> <method name="NameHasOwner"> <arg direction="in" type="s"/> <arg direction="out" type="b"/> </method> <method name="ListNames"> <arg direction="out" type="as"/> </method> <method name="ListActivatableNames"> <arg direction="out" type="as"/> </method> <method name="AddMatch"> <arg direction="in" type="s"/> </method> <method name="RemoveMatch"> <arg direction="in" type="s"/> </method> <method name="GetNameOwner"> <arg direction="in" type="s"/> <arg direction="out" type="s"/> </method> <method name="ListQueuedOwners"> <arg direction="in" type="s"/> <arg direction="out" type="as"/> </method> <method name="GetConnectionUnixUser"> <arg direction="in" type="s"/> <arg direction="out" type="u"/> </method> <method name="GetConnectionUnixProcessID"> <arg direction="in" type="s"/> <arg direction="out" type="u"/> </method> <method name="GetConnectionSELinuxSecurityContext"> <arg direction="in" type="s"/> <arg direction="out" type="ay"/> </method> <method name="ReloadConfig"> </method> <method name="GetId"> <arg direction="out" type="s"/> </method> <signal name="NameOwnerChanged"> <arg type="s"/> <arg type="s"/> <arg type="s"/> </signal> <signal name="NameLost"> <arg type="s"/> </signal> <signal name="NameAcquired"> <arg type="s"/> </signal> </interface> </node> "
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.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 --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" ]
$ 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 "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <node name="TestObj"/> </node> "
$ 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 "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg name="data" direction="out" type="s"/> </method> </interface> <interface name="org.freedesktop.DBus.Properties"> <method name="Get"> <arg name="interface" direction="in" type="s"/> <arg name="propname" direction="in" type="s"/> <arg name="value" direction="out" type="v"/> </method> <method name="Set"> <arg name="interface" direction="in" type="s"/> <arg name="propname" direction="in" type="s"/> <arg name="value" direction="in" type="v"/> </method> <method name="GetAll"> <arg name="interface" direction="in" type="s"/> <arg name="props" direction="out" type="a{sv}"/> </method> </interface> <interface name="org.fmddlmyy.Test.Basic"> <method name="Add"> <arg name="arg0" type="i" direction="in"/> <arg name="arg1" type="i" direction="in"/> <arg name="ret" type="i" direction="out"/> </method> </interface> </node> "
$ 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" ]
$ 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 "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <node name="org"/> </node> "
$ 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 "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <node name="bluez"/> </node> "
$ 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 "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node name="/org/bluez"> <interface name="org.bluez.Manager"> <method name="InterfaceVersion"> <arg type="u" direction="out"/> </method> <method name="DefaultAdapter"> <arg type="s" direction="out"/> </method> <method name="FindAdapter"> <arg type="s" direction="in"/> <arg type="s" direction="out"/> </method> <method name="ListAdapters"> <arg type="as" direction="out"/> </method> <method name="FindService"> <arg type="s" direction="in"/> <arg type="s" direction="out"/> </method> <method name="ListServices"> <arg type="as" direction="out"/> </method> <method name="ActivateService"> <arg type="s" direction="in"/> <arg type="s" direction="out"/> </method> <signal name="AdapterAdded"> <arg type="s"/> </signal> <signal name="AdapterRemoved"> <arg type="s"/> </signal> <signal name="DefaultAdapterChanged"> <arg type="s"/> </signal> <signal name="ServiceAdded"> <arg type="s"/> </signal> <signal name="ServiceRemoved"> <arg type="s"/> </signal> </interface> <interface name="org.bluez.Database"> <method name="AddServiceRecord"> <arg type="ay" direction="in"/> <arg type="u" direction="out"/> </method> <method name="AddServiceRecordFromXML"> <arg type="s" direction="in"/> <arg type="u" direction="out"/> </method> <method name="UpdateServiceRecord"> <arg type="u" direction="in"/> <arg type="ay" direction="in"/> </method> <method name="UpdateServiceRecordFromXML"> <arg type="u" direction="in"/> <arg type="s" direction="in"/> </method> <method name="RemoveServiceRecord"> <arg type="u" direction="in"/> </method> <method name="RegisterService"> <arg type="s" direction="in"/> <arg type="s" direction="in"/> <arg type="s" direction="in"/> </method> <method name="UnregisterService"> <arg type="s" direction="in"/> </method> <method name="RequestAuthorization"> <arg type="s" direction="in"/> <arg type="s" direction="in"/> </method> <method name="CancelAuthorizationRequest"> <arg type="s" direction="in"/> <arg type="s" direction="in"/> </method> </interface> <interface name="org.bluez.Security"> <method name="RegisterDefaultPasskeyAgent"> <arg type="s" direction="in"/> </method> <method name="UnregisterDefaultPasskeyAgent"> <arg type="s" direction="in"/> </method> <method name="RegisterPasskeyAgent"> <arg type="s" direction="in"/> <arg type="s" direction="in"/> </method> <method name="UnregisterPasskeyAgent"> <arg type="s" direction="in"/> <arg type="s" direction="in"/> </method> <method name="RegisterDefaultAuthorizationAgent"> <arg type="s" direction="in"/> </method> <method name="UnregisterDefaultAuthorizationAgent"> <arg type="s" direction="in"/> </method> </interface> <node name="service_audio"/> <node name="service_input"/> <node name="service_network"/> <node name="service_serial"/> </node> "