上篇文章<<
D-Bus實例介紹
>>中簡要介紹了 D-Bus
的基本概念,其中提到 systemd
、 NetworkManager
等系統(tǒng)服務(wù)導(dǎo)出了 D-Bus API
供其他程序來調(diào)用。本文通過示例來說明這些API的查找與調(diào)用。
上篇文章
我們提到 D-Bus
的 object
可以實現(xiàn)多個 Interface
。
D-Bus
規(guī)范
中標準化了一些接口,這些接口對于我們調(diào)用其他服務(wù)提供的D-Bus API非常有幫助。 我們主要來看其中的兩個: 它有一個方法: org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
它會返回一個包含有對象(object), 接口(interface), 方法(methods), 信號(signals),屬性(properties)等信息的XML字符串。對象如果實現(xiàn)這個接口, 我們就可以通過調(diào)用該方法了解這個對象對外提供的所有信息。 XML字符串的解析方法可以參考官方文檔:
https://dbus./doc/dbus-specification.html#introspection-format 它有三個方法: org.freedesktop.DBus.Properties.Get (in STRING interface_name,
in STRING property_name,
out VARIANT value);
org.freedesktop.DBus.Properties.Set (in STRING interface_name,
in STRING property_name,
in VARIANT value);
org.freedesktop.DBus.Properties.GetAll (in STRING interface_name,
out DICT<STRING,VARIANT> props);
如果對象實現(xiàn)了該接口, 那么可以通過調(diào)用這些方法來對該對象的屬性(properties)進行操作。 NetworkManager
服務(wù)都實現(xiàn)了這些標準接口。我們通過 busctl
工具來看一下具體的信息。
busctl
是 systemd
提供的一個 D-Bus
操作工具,功能非常強大,在之前的文章中我們也用它來查看當(dāng)前的 D-Bus
服務(wù)。具體用法可以參考
Man Page
首先,使用 busctl
來查看 org.freedesktop.NetworkManager
服務(wù)提供了哪些對象( objects
): [root@centos1 dbus]# busctl tree org.freedesktop.NetworkManager
├─/com
│ └─/com/redhat
│ └─/com/redhat/ifcfgrh1
└─/org
└─/org/freedesktop
└─/org/freedesktop/NetworkManager
├─/org/freedesktop/NetworkManager/ActiveConnection
│ └─/org/freedesktop/NetworkManager/ActiveConnection/0
├─/org/freedesktop/NetworkManager/AgentManager
├─/org/freedesktop/NetworkManager/Devices
│ ├─/org/freedesktop/NetworkManager/Devices/0
│ ├─/org/freedesktop/NetworkManager/Devices/1
│ └─/org/freedesktop/NetworkManager/Devices/2
├─/org/freedesktop/NetworkManager/IP4Config
│ ├─/org/freedesktop/NetworkManager/IP4Config/0
│ ├─/org/freedesktop/NetworkManager/IP4Config/1
│ └─/org/freedesktop/NetworkManager/IP4Config/2
├─/org/freedesktop/NetworkManager/IP6Config
│ ├─/org/freedesktop/NetworkManager/IP6Config/0
│ ├─/org/freedesktop/NetworkManager/IP6Config/1
│ └─/org/freedesktop/NetworkManager/IP6Config/2
└─/org/freedesktop/NetworkManager/Settings
└─/org/freedesktop/NetworkManager/Settings/0
接著,來查看某個對象實現(xiàn)的接口及其成員: [root@centos1 dbus]# busctl introspect org.freedesktop.NetworkManager /org/freedesktop/NetworkManager/Devices/0
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
org.freedesktop.NetworkManager.Device interface - - -
.Delete method - - -
.Disconnect method - - -
.ActiveConnection property o "/" emits-change
.Autoconnect property b false emits-change writable
.AvailableConnections property ao 0 emits-change
.Capabilities property u 7 emits-change
.DeviceType property u 14 emits-change
.Dhcp4Config property o "/" emits-change
.Dhcp6Config property o "/" emits-change
.Driver property s "unknown" emits-change
.DriverVersion property s "" emits-change
.FirmwareMissing property b false emits-change
.FirmwareVersion property s "" emits-change
.Interface property s "lo" emits-change
.Ip4Address property u 16777343 emits-change
.Ip4Config property o "/org/freedesktop/NetworkManager/IP4C... emits-change
.Ip6Config property o "/org/freedesktop/NetworkManager/IP6C... emits-change
.IpInterface property s "lo" emits-change
.Managed property b false emits-change
.Mtu property u 65536 emits-change
.PhysicalPortId property s "" emits-change
.State property u 10 emits-change
.StateReason property (uu) 10 0 emits-change
.Udi property s "/sys/devices/virtual/net/lo" emits-change
.StateChanged signal uuu - -
org.freedesktop.NetworkManager.Device.Generic interface - - -
.HwAddress property s "00:00:00:00:00:00" emits-change
.TypeDescription property s "loopback" emits-change
.PropertiesChanged signal a{sv} - -
返回結(jié)果中顯示了該對象實現(xiàn)的接口及其方法(methods)、信息(signals)、屬性(properties)等信息,屬性值也被列出。 如果我們需要獲取特定的屬性值,還可以使用 busctl
的 get-property
子命令單獨獲取。 比如,我們獲取某個網(wǎng)卡的名稱: [root@centos1 python]# busctl get-property org.freedesktop.NetworkManager /org/freedesktop/NetworkManager/Devices/1 org.freedesktop.NetworkManager.Device Interface
s "enp0s3"
上面我們使用 busctl
工具來示范了 D-Bus
服務(wù)API的調(diào)用方式。下面,我們再通一個 Python
程序來說明如何在程序中實現(xiàn)屬性獲取。 源碼如下: import dbus
from pprint import pprint
from dbus import SystemBus
from dbus import Interface
from xml.etree import ElementTree
def print_network_ifaces(bus, service, object_path):
try:
if object_path == "/org/freedesktop/NetworkManager/Devices":
return
obj = bus.get_object(service, object_path)
interface = Interface(obj, 'org.freedesktop.DBus.Properties')
m = interface.get_dbus_method('Get', dbus_interface=None)
ifacename = m('org.freedesktop.NetworkManager.Device', 'Interface')
print(ifacename)
except Exception, err:
print err
def rec_intro(bus, service, object_path, callback):
callback(bus, service, object_path)
obj = bus.get_object(service, object_path)
interface = Interface(obj, 'org.freedesktop.DBus.Introspectable')
xmlstring = interface.Introspect()
for child in ElementTree.fromstring(xmlstring):
if child.tag == 'node':
if object_path == '/':
object_path = ''
new_path = '/' . join((object_path, child.attrib['name']))
rec_intro(bus, service, new_path, callback)
bus = SystemBus()
rec_intro(bus, 'org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Devices', print_network_ifaces)
我們的程序中首先調(diào)用標準接口 org.freedesktop.DBus.Introspectable
的方法 Introspect
拿到所有網(wǎng)絡(luò)接口對象,然后調(diào)用標準接口 org.freedesktop.DBus.Properties
的方法 Get
獲取屬性 Interface
的值,從而獲取網(wǎng)絡(luò)接口名稱。 系統(tǒng)本身的許多服務(wù)都提供了 D-Bus
API, 在許多場景下通過調(diào)用這些API可以非常便捷地實現(xiàn)我們的功能需求。
|