dbus-glib编程3:消息和消息总线 dbus-send的使用

论坛 期权论坛 脚本     
匿名技术用户   2021-1-4 23:38   291   0

1、从例子开始

我写了一个最简单的dbus服务器,它通过dbus提供了一个加法的接口。 大家可以https://download.csdn.net/download/cyf15238622067/12797794这个例子。这是一个autotool工程,大家解包后,执行:

./autogen.sh
./configure
make

然后在src目录运行:

./example-service

这时再运行d-feet,连接session bus,在“Bus Name”窗口会看到一个叫“org.fmddlmyy.Test”连接名。

选择“org.fmddlmyy.Test”,在右侧窗口点击展开“Object Paths”->“/TestObj”->“Interfaces”->“org.fmddlmyy.Test.Basic”->“Methods”,可以看到一个Add方法。双击Add方法,弹出下面这个对话框:

在Parameters窗口输入“1,2”,点击“运行”按钮,然后在“Output”窗口我们看到了输出结果。我们刚刚创建了一个dbus服务并调用了它。

流程理解:

应用程序A和消息总线连接,这个连接获取一个众所周知的(Bus Name)公共连接名A。应用程序A中有对象(object) A1 有接口(Interface)I1,接口I1 有 方法M1.应用程序B和消息总线连接,要求调用连接A上对象A1的接口I1的方法M1.

在上面的加法例子中,上面这段话可以实例化为:应用程序example-service和会话总线连接。这个连接获取了一个众所周知的公共名“org.fmddlmyy.Test”。 应用程序example-servic中有对象“/TestObj”提供了接口“org.fmddlmyy.Test.Basic”,接口“org.fmddlmyy.Test.Basic”有方法“Add”。 应用程序d-feet和会话总线连接,要求调用连接“org.fmddlmyy.Test”上对象“/TestObj”的接口“org.fmddlmyy.Test.Basic”的方法“Add”。

应用程序B调用应用程序A的方法,其实就是应用程序B向应用程序A发送了一个类型为“method_call”的消息。 应用程序A通过一个类型为“method_retutn”的消息将返回值发给应用程序B。我们简单介绍一下D-Bus总线上的消息。

2、D-Bus的消息

上一讲说过最基本的D-Bus协议是一对一的通信协议。与直接使用socket不同,D-Bus是面向消息的协议。 D-Bus的所有功能都是通过在连接上流动的消息完成的。

2.1、消息类型

D-Bus有四种类型的消息:

  • method_call 方法调用
  • method_return 方法返回
  • error 错误
  • signal 信号

前面介绍的远程方法调用就用到了method_call和method_return消息。顾名思义,在发生错误时会产生error消息。 如果把method_call看作打电话,那么signal消息就是来电了。后面还会详细讨论。

2.2、dbus-send和dbus-monitor

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默认监视会话总线。执行:

add函数调试

$ 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 --help
Usage: dbus-send [--help] [--system | --session | --bus=ADDRESS | --peer=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]

调用远程方法的一般形式是:

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

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

锁屏调试

$ dbus-send --session --type=method_call --print-reply --dest=org.cinnamon.ScreenSaver /org/cinnamon/ScreenSaver org.cinnamon.ScreenSaver.Lock string:"1234567890"

3消息总线的方法和信号

3.1、概述

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

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

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

3.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 time=1599017747.068176 sender=org.freedesktop.DBus -> destination=:1.342 serial=3 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">
<method name="Hello">
<arg direction="out" type="s"/>
</method>

.......................

   <signal name="NameLost">
      <arg type="s"/>
    </signal>
    <signal name="NameAcquired">
      <arg type="s"/>
    </signal>
  </interface>
</node>
"

从输出可以看到会话总线对象支持标准接口“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.1、从ListName到d-feet的基本逻辑

用dbus-send调用: 返回消息总线上已连接的所有连接名,包括所有公共名和唯一名

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

输出为:

method return time=1599018167.391110 sender=org.freedesktop.DBus -> destination=:1.343 serial=3 reply_serial=2
array [
string "org.freedesktop.DBus"
string ":1.304"
string ":1.205"
string "org.freedesktop.Notifications"
string ":1.7"
string ":1.327"
string ":1.305"
string ":1.206"
string "org.freedesktop.network-manager-applet"
string ":1.8"
string ":1.328"
string ":1.306"
string ":1.9"
string ":1.329"
string ":1.307"
string "org.Nemo"
string "org.freedesktop.systemd1"
string ":1.309"
string "com.sublimetext.three"
string "org.gtk.vfs.Daemon"
string "org.pulseaudio.Server"
string "org.gnome.SessionManager"
string "org.cinnamon.SettingsDaemon.KeybindingHandler"
string ":1.60"
string ":1.61"
string "org.gnome.evolution.dataserver.Sources5"
string ":1.40"
string "org.gnome.Terminal"
string "org.gtk.vfs.UDisks2VolumeMonitor"
string "org.a11y.Bus"
string ":1.64"
string ":1.42"
string ":1.20"
string ":1.65"
string "org.gnome.Identity"
string ":1.43"
string ":1.21"
string ":1.44"
string "org.gnome.keyring"
string ":1.22"
string ":1.230"
string "org.freedesktop.PackageKit"
string ":1.45"
string ":1.23"
string ":1.330"
string ":1.154"
string ":1.68"
string "org.NemoDesktop"
string ":1.46"
string "org.gnome.dfeet"
string ":1.69"
string "org.gnome.Caribou.Keyboard"
string ":1.47"
string ":1.25"
string ":1.332"
string ":1.299"
string "org.Cinnamon"
string ":1.48"
string ":1.26"
string ":1.49"
string ":1.27"
string "org.cinnamon.SettingsDaemon.XRANDR_2"
string ":1.28"
string "org.gtk.vfs.GPhoto2VolumeMonitor"
string ":1.29"
string "ca.desrt.dconf"
string "org.freedesktop.Tracker1.Miner.Applications"
string "org.gnome.SettingsDaemon"
string ":1.315"
string "org.freedesktop.ReserveDevice1.Audio0"
string "org.freedesktop.Tracker1"
string "org.freedesktop.ScreenSaver"
string "org.gnome.evolution.dataserver.Calendar7"
string "org.gtk.vfs.mountpoint_3116"
string "org.gnome.Magnifier"
string "org.gtk.vfs.AfcVolumeMonitor"
string "org.freedesktop.FileManager1"
string "org.gtk.vfs.mountpoint_1875"
string "org.PulseAudio1"
string "org.Cinnamon.Melange"
string "org.Cinnamon.LookingGlass"
string "org.gnome.Panel"
string "org.gtk.vfs.GoaVolumeMonitor"
string "org.fmddlmyy.Test"
string "org.gnome.Evolution-alarm-notify"
string ":1.92"
string ":1.71"
string "org.gnome.OnlineAccounts"
string "org.cinnamon.SettingsDaemon.Power"
string "org.freedesktop.portal.IBus"
string ":1.72"
string "org.gnome.evolution.dataserver.AddressBook9"
string ":1.50"
string ":1.74"
string "org.gtk.vfs.Metadata"
string ":1.52"
string ":1.30"
string ":1.75"
string ":1.53"
string ":1.31"
string "org.cinnamon.ScreenSaver"
string ":1.76"
string ":1.54"
string ":1.10"
string ":1.32"
string "org.gnome.Caribou.Daemon"
string "org.gtk.vfs.mountpoint_dnssd"
string ":1.99"
string ":1.55"
string ":1.11"
string ":1.33"
string ":1.56"
string ":1.12"
string ":1.34"
string ":1.57"
string ":1.0"
string ":1.13"
string ":1.35"
string ":1.58"
string ":1.14"
string ":1.36"
string ":1.343"
string "org.Cinnamon.Slideshow"
string "org.freedesktop.Tracker1.Miner.Files"
string ":1.15"
string "org.freedesktop.secrets"
string ":1.37"
string "org.cinnamon.SettingsDaemon.Sound"
string ":1.300"
string "org.gtk.vfs.MTPVolumeMonitor"
string ":1.16"
string ":1.38"
string ":1.301"
string "org.freedesktop.IBus.Panel.Extension.Gtk3"
string ":1.17"
string ":1.39"
string "org.gnome.Screenshot"
string ":1.5"
string ":1.18"
string ":1.303"
string "org.gnome.Software"
string ":1.6"
string "org.freedesktop.IBus"
string ":1.19"
]

返回所有可以启动的服务名

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListActivatableNames
method return time=1599018192.077679 sender=org.freedesktop.DBus -> destination=:1.345 serial=3 reply_serial=2
array [
string "org.freedesktop.DBus"
string "org.gnome.Gnote"
string "org.gnome.ChromeGnomeShell"
string "org.gnome.Rygel1"
string "org.gnome.Characters"
string "org.gnome.OnlineMiners.GData"
string "org.Nemo"
string "org.freedesktop.systemd1"
string "org.gnome.OnlineMiners.Zpj"
string "org.freedesktop.Tracker1.Miner.Extract"
string "org.xfce.Xfconf"
string "org.gnome.Logs"
string "org.fedoraproject.Config.Printing"
string "org.freedesktop.ColorHelper"
string "org.gtk.vfs.Daemon"
string "org.gnome.NautilusPreviewer"
string "org.kde.kwalletd"
string "org.gnome.ControlCenter.SearchProvider"
string "org.gnome.evolution.dataserver.Sources5"
string "org.Cinnamon.HotplugSniffer"
string "org.gnome.Terminal"
string "org.a11y.Bus"
string "org.gtk.vfs.UDisks2VolumeMonitor"
string "org.gnome.OnlineMiners.Facebook"
string "org.gnome.OnlineMiners.Flickr"
string "org.gnome.Identity"
string "org.gnome.keyring"
string "org.gnome.Shell.CalendarServer"
string "org.gnome.font-viewer"
string "org.gnome.OnlineMiners.MediaServer"
string "org.freedesktop.PackageKit"
string "org.freedesktop.Tracker1.Writeback"
string "org.gnome.Characters.BackgroundService"
string "com.intel.dleyna-server"
string "ca.desrt.dconf"
string "org.bluez.obex"
string "org.gnome.FileRoller"
string "org.gnome.evolution.dataserver.UserPrompter0"
string "org.gtk.vfs.GPhoto2VolumeMonitor"
string "org.freedesktop.Tracker1.Miner.Applications"
string "org.freedesktop.Tracker1"
string "org.gnome.evince.Daemon"
string "org.gnome.evolution.dataserver.Calendar7"
string "org.gtk.vfs.AfcVolumeMonitor"
string "org.freedesktop.FileManager1"
string "org.gnome.Totem"
string "org.gnome.SoundJuicer"
string "org.kde.kwalletd5"
string "org.gnome.Nautilus"
string "org.gnome.baobab"
string "org.gnome.Contacts"
string "org.gtk.vfs.GoaVolumeMonitor"
string "org.Cinnamon.Melange"
string "org.gtk.GLib.PACRunner"
string "org.gnome.Calculator.SearchProvider"
string "org.gnome.ArchiveManager1"
string "org.fmddlmyy.Test"
string "org.gnome.Cheese"
string "org.gnome.Shell.PortalHelper"
string "org.freedesktop.portal.IBus"
string "org.gnome.OnlineAccounts"
string "org.blueman.Applet"
string "org.gnome.evolution.dataserver.AddressBook9"
string "org.gtk.vfs.Metadata"
string "org.gnome.Rhythmbox3"
string "org.cinnamon.ScreenSaver"
string "org.gnome.Shell.HotplugSniffer"
string "org.gnome.keyring.SystemPrompter"
string "org.gnome.Caribou.Daemon"
string "org.gnome.DiskUtility"
string "org.gnome.gedit"
string "org.gnome.ControlCenter"
string "org.Cinnamon.Slideshow"
string "org.freedesktop.secrets"
string "org.freedesktop.Tracker1.Miner.Files"
string "org.gnome.Contacts.SearchProvider"
string "org.gtk.vfs.MTPVolumeMonitor"
string "org.gnome.keyring.PrivatePrompter"
string "org.gnome.Devhelp"
string "org.gnome.Screenshot"
string "org.gnome.OnlineMiners.Owncloud"
string "org.freedesktop.IBus"
string "org.gnome.Software"
]

这是会话总线当前已连接的连接名。在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 "<!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>
"

"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 "<!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>
"

我们也可以用python脚本调用ListActivatableNames。例如:写一个叫dls.py的脚本:

#!/usr/bin/env python3
import dbus
bus=dbus.SystemBus()
bus_obj=bus.get_object('org.freedesktop.DBus', '/')
iface=dbus.Interface(bus_obj, 'org.freedesktop.DBus')
names=iface.ListActivatableNames()
for n in names:
print(n)

运行 python3 dls.py | sort

使用python脚本调用dbus接口是不是很简单。如果你看过dbus-glib的代码(后面会讲解),你对python的简洁会有更深刻的感触。如果你执行:

$ cat /usr/share/dbus-1/services/*|grep Name|awk -F= '{print $2}'|sort

这条命令的输出与ListActivatableNames的输出是不是基本相同?你能看懂上面这条命令吗?它将"/usr/share/dbus-1/services/"下所有文件交给grep筛选出包含“Name”的行。将包含“Name”的行交给awk处理,awk用"="作为列分隔符,取出第二列然后交给sort排序后输出。 "/usr/share/dbus-1/services/"目录就是dbus放service文件的地方。需要自动启动的服务器会在这个目录放一个service文件,例如:

$ cat /usr/share/dbus-1/services/dhcdbd.service
[D-BUS Service]
Name=com.redhat.dhcp
Exec=/usr/sbin/dhcdbd

Name是服务器的公共名,Exec是服务器的执行路径。在客户请求一个服务,但该服务还没有启动时。dbus会根据service文件自动启动服务。我们再写一个调用“org.fmddlmyy.Test”的Add接口的python脚本:

#!/usr/bin/env python3
import dbus
bus = dbus.SessionBus()
obj = bus.get_object( 'org.fmddlmyy.Test', '/TestObj' )
iface = dbus.Interface(obj, 'org.fmddlmyy.Test.Basic')
sum = iface.Add(100, 999)
print(sum)

在启动“org.fmddlmyy.Test”服务器前调用这个脚本

$ ./add.py

会得到错误输出:

...
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.ServiceUnknown: The name org.fmddlmyy.Test was not provided by any .service files

我们编辑一个service文件:

$ cat org.fmddlmyy.Test.service
[D-BUS Service]
Name=org.fmddlmyy.Test
Exec=/home/......../example-service

把这个文件放到"/usr/share/dbus-1/services/"目录后,再执行add.py:

$ sudo cp org.fmddlmyy.Test.service /usr/share/dbus-1/services/
$ python3 add.py
1099

这次dbus自动启动了服务器,我们的客户脚本得到了正确的输出,你有没有感到dbus的神奇?dbus在自动启动服务器后,不会自动关闭。如果没人管它,这个服务器会一直开着。

其它方法

再演示几个“org.freedesktop.DBus”接口的方法。NameHasOwner判断有没有连接拥有指定的公共名:

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.NameHasOwner string:"org.cinnamon.ScreenSaver"
method return time=1599019017.553426 sender=org.freedesktop.DBus -> destination=:1.357 serial=3 reply_serial=2
boolean true

GetNameOwner返回公共名对应的唯一名:

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.GetNameOwner string:"org.cinnamon.ScreenSaver"
method return time=1599019066.399711 sender=org.freedesktop.DBus -> destination=:1.358 serial=3 reply_serial=2
string ":1.154"

GetConnectionUnixUser返回指定连接对应的服务器进程的Unix用户id:

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixUser string:":1.154"

method return time=1599019230.815537 sender=org.freedesktop.DBus -> destination=:1.360 serial=3 reply_serial=2
uint32 1000

$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixUser string:"org.cinnamon.ScreenSaver"
method return time=1599019114.397392 sender=org.freedesktop.DBus -> destination=:1.359 serial=3 reply_serial=2
uint32 1000

这就是我的用户id:

$ id -u username
1000

GetId返回消息总线的ID:

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

输出为:

method return time=1599019335.364636 sender=org.freedesktop.DBus -> destination=:1.361 serial=3 reply_serial=2
string "38fb0b90b037c49cdbd2f2905f4cc509"

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP