运行:
$ dbus-send --system --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListActivatableNames
和
$ dbus-send --session --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListActivatableNames
返回的数据是一样的。在我的电脑上返回的数据是:
array [ string "org.freedesktop.DBus" string "org.freedesktop.Notifications" string "net.ekiga.helper" string "org.freedesktop.PowerManagement" string "org.freedesktop.Tracker" string "org.freedesktop.SystemToolsBackends.GroupsConfig" string "org.freedesktop.SystemToolsBackends.NTPConfig" string "org.gnome.Tomboy" string "org.freedesktop.SystemToolsBackends.HostsConfig" string "org.freedesktop.SystemToolsBackends.NFSConfig" string "org.freedesktop.SystemToolsBackends" string "net.ekiga.instance" string "org.gnome.GnomeVFS.Daemon" string "com.redhat.dhcp" string "org.freedesktop.SystemToolsBackends.TimeConfig" string "org.freedesktop.SystemToolsBackends.IfacesConfig" string "org.freedesktop.SystemToolsBackends.ServicesConfig" string "org.gnome.Rhythmbox" string "org.freedesktop.SystemToolsBackends.Platform" string "org.freedesktop.SystemToolsBackends.UsersConfig" string "org.freedesktop.SystemToolsBackends.SMBConfig" string "org.gnome.SettingsDaemon" ]
我们也可以用python脚本调用ListActivatableNames。例如:写一个叫dls.py的脚本:
$ cat dls.py #!/usr/bin/env python 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
运行:
$ ./dls.py |sort
输出为:
com.redhat.dhcp net.ekiga.helper net.ekiga.instance org.freedesktop.DBus org.freedesktop.Notifications org.freedesktop.PowerManagement org.freedesktop.SystemToolsBackends org.freedesktop.SystemToolsBackends.GroupsConfig org.freedesktop.SystemToolsBackends.HostsConfig org.freedesktop.SystemToolsBackends.IfacesConfig org.freedesktop.SystemToolsBackends.NFSConfig org.freedesktop.SystemToolsBackends.NTPConfig org.freedesktop.SystemToolsBackends.Platform org.freedesktop.SystemToolsBackends.ServicesConfig org.freedesktop.SystemToolsBackends.SMBConfig org.freedesktop.SystemToolsBackends.TimeConfig org.freedesktop.SystemToolsBackends.UsersConfig org.freedesktop.Tracker org.gnome.GnomeVFS.Daemon org.gnome.Rhythmbox org.gnome.SettingsDaemon org.gnome.Tomboy
使用python脚本调用dbus接口是不是很简单。如果你看过dbus-glib的代码(后面会讲解),你对python的简洁会有更深刻的感触。如果你执行:
$ cat /usr/share/dbus-1/services/*|grep Name|awk -F= '{print $2}'|sort
你会得到:
com.redhat.dhcp net.ekiga.helper net.ekiga.instance org.freedesktop.Notifications org.freedesktop.PowerManagement org.freedesktop.SystemToolsBackends org.freedesktop.SystemToolsBackends.GroupsConfig org.freedesktop.SystemToolsBackends.HostsConfig org.freedesktop.SystemToolsBackends.IfacesConfig org.freedesktop.SystemToolsBackends.NFSConfig org.freedesktop.SystemToolsBackends.NTPConfig org.freedesktop.SystemToolsBackends.Platform org.freedesktop.SystemToolsBackends.ServicesConfig org.freedesktop.SystemToolsBackends.SMBConfig org.freedesktop.SystemToolsBackends.TimeConfig org.freedesktop.SystemToolsBackends.UsersConfig org.freedesktop.Tracker org.gnome.GnomeVFS.Daemon org.gnome.Rhythmbox org.gnome.SettingsDaemon org.gnome.Tomboy
这条命令的输出与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脚本:
$ cat add.py #!/usr/bin/env python 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/lvjie/work/dbus/hello-dbus3-0.1/src/example-service
把这个文件放到"/usr/share/dbus-1/services/"目录后,再执行add.py:
$ sudo cp org.fmddlmyy.Test.service /usr/share/dbus-1/services/ $ cd ../../py $ ./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.fmddlmyy.Test"
输出为:
method return sender=org.freedesktop.DBus -> dest=:1.31 reply_serial=2 boolean true
GetNameOwner返回公共名对应的唯一名:
$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.GetNameOwner string:"org.fmddlmyy.Test"
输出为:
method return sender=org.freedesktop.DBus -> dest=:1.32 reply_serial=2 string ":1.30"
GetConnectionUnixUser返回指定连接对应的服务器进程的Unix用户id:
$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.GetConnectionUnixUser string:":1.30"
输出为:
method return sender=org.freedesktop.DBus -> dest=:1.33 reply_serial=2 uint32 1000
这就是我的用户id:
$ id -u lvjie 1000
GetId返回消息总线的ID:
$ dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.GetId
输出为:
method return sender=org.freedesktop.DBus -> dest=:1.34 reply_serial=2 string "dc209fee5f8ce01b0c23da0049668f11"
这一集有一些python代码。即使你没有学过python,我也建议你看一看、试一试。其实我也没有学过python。小时候,好像听过什么德国 人一边看说明书一边开飞机的笑话。这或许是吹牛,但对于程序员来说一边查手册一边用新语言写一些简单程序应该不算困难。下一讲我们要写一个略大点的 python程序。虽然我习惯于C/C++的事必躬亲,但不可否认python确实是很有魅力的语言,难怪在嵌入式环境也有那么多人用python作原型 开发。