Meego Wiki
Views
From MeeGo wiki
(Difference between revisions)
Jump to: navigation, search
(dbus-monitor (command line))
(dbus-monitor (command line))
Line 125: Line 125:
</pre>
</pre>
-
It's possible to filter which signals/methods are reported, using watch expressions, like this example from the man page for <code>dbus-monitor</code>:
+
It's possible to filter which signals/methods are reported, using watch expressions, like this example from the man page for <code>dbus-monitor</code> to use dbus-monitor "to watch for the gnome typing monitor to say things":
<pre>
<pre>

Revision as of 17:00, 22 June 2010

Contents

Introduction

D-Bus is an Inter Process Communication (IPC) system, providing a mechanism for applications running on a single machine to "talk" to each other. Due to its focus on being a message bus for local applications, D-Bus has some nice features compared to alternative IPC mechanisms: these include the capability to autostart applications which are not active but which have been sent a message; and the ability to ensure that only a single instance of an application is ever running.

Message buses

The core D-Bus protocol is a 2-way, asynchronous, binary protocol. While it is possible to use for direct application to application communication (using libdbus - not recommended), the most common usage of the protocol is via a D-Bus message bus server. The server is connected to each client using D-Bus, and routes each message from the application which sent it its intended recipient. Each application which exposes its capabilities on the bus is known as a service. (An application doesn't have to expose any services to make use of the bus: it can just send messages to other applications which do provide services.)

D-Bus message bus and applications

There are actually multiple D-Bus message buses running on MeeGo (and on your average Linux system) at any one time, of two types:

  • The system bus is a machine-global, single instance of the daemon with security restrictions on what messages it will accept. It's used for system-wide communication and communication between the user desktop and the operating system.
  • A session bus is created for each user session. It allows applications within that user session to communicate. Most MeeGo D-Bus services (connman etc.) communicate via the session bus.

Services, trees, interfaces, and objects

Services on a D-Bus expose a tree of objects to interact with. Each service has a root path; from the root come branches, one for each object provided by that service. Each object on a service tree is addressable by an object path.

Object paths are typically in a reverse-domain name format, akin to Java package names; for example, org.freedesktop.Tracker1 for the Tracker (content framework) root path.

Interfaces are the contract between an object and its callers, much like interfaces in Java, GObject etc.. An interface, as in most object-oriented programming environments, defines the methods and properties an object exposes. In addition, D-Bus interfaces can also contain signals. Signals provide a way for objects to notify other objects about events which happen to them: for example, a Door interface might provide a signal to other objects when it is opened, perhaps called door-opened. (A nearby Doorman object might listen out for door-opened signals, so it knows when people come into the building.)

Each D-Bus object implements one or more interfaces. Most implement two standard interfaces as a minimum, org.freedesktop.DBus.Introspectable and org.freedesktop.DBus.Properties:

  • The Introspectable interface specifies a single method, Introspect(). Calling this method on an object returns a string of XML which defines the interfaces (and the properties, signals and methods of those interfaces) implemented by that object.
  • The Properties interface specifies three standard methods for getting and setting an object's properties: Get(), GetAll(), and Set().
    • Get() takes the interface name and a property name as arguments and returns the value of the specified property.
    • GetAll() takes the interface name and returns a dictionary of property name to value mappings.
    • Set() takes the interface name, a property name and the value to set for the property as arguments.

Investigating and debugging D-Bus services

d-feet (graphical tool)

Often the easiest way to get started investigating a service on the Bus is to use D-Feet, a graphical D-Bus debugging tool. Here's an example of it monitoring the system bus on a MeeGo netbook:

D-Feet graphic D-Bus debugging tool

Using D-Feet, one can browse the tree of objects available for each service.

D-Feet uses the Introspect() method of the Introspection interface to determine what methods, properties and signals an object implements. It even allows execution of the available methods using a Python-like syntax for specifying arguments.

D-Feet is available in the MeeGo package repositories and can be installed with:

sudo yum install d-feet

Using d-feet

D-Feet can be started from the command line with:

 d-feet

You can then connect to either the system bus or the session bus, using the connect icon:

d-feet connect icon

The address to enter depends on the bus type you want to monitor:

  • The system bus: the system bus on MeeGo 1.0 is located at:
    unix:path=/var/run/dbus/system_bus_socket
    You can find the system bus path manually by grepping /etc/dbus-1/system.conf for the <listen> setting.
  • The session bus: you can find the address for the current user's D-Bus session with:
    $env | grep DBUS_SESSION_BUS_ADDRESS
    

    Example output:

    DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-6H89TrarMk,guid=a72013b7b9456e7a3eca017100000038
    
    You need the bit after the first '=' sign (starting unix:abstract).

Once you've connected to a bus, you'll get a list of bus names on the left. Click on one to see the available object paths in the right panel (see the screenshot above). The root path (/) will usually have some useful interfaces you can poke. It's also possible to invoke methods on the services you discover: for example, here's the output of the EnumerateDevices method of the org.freedesktop.UDisks interface:

Executing a method on a D-Bus service using d-feet

To execute a method which takes parameter, supply them in Python syntax, separated by commas. For example, here's the libsocialweb UpdateStatus method being executed over D-Bus from d-feet:

Executing a libsocialweb method over D-Bus from d-feet

Note that the method has two parameters:

  1. s status_message: a string representing the status update; I used "Using d-feet to invoke libsocialweb methods over D-Bus" as my status update.
  2. a{ss} fields: a dictionary mapping strings to strings; I used {} and (no data except the update string).

For more on the valid D-Bus types, see the D-Bus specification.

dbus-monitor (command line)

dbus-monitor is a command line tool which displays signals sent by and messages sent to a D-Bus bus. Invoke it with:

dbus-monitor --system

for the system bus; or with:

dbus-monitor --session

for the session bus (the default).

Here's the example of some output from the session bus (Banshee's media indexing back-end Tracker sending a signal to say it's going to process metadata from files; then the SparqlQuery method being called on Tracker):

signal sender=:1.55 -> dest=(null destination) serial=204 path=/org/freedesktop/Tracker1/Miner/Files; 
interface=org.freedesktop.Tracker1.Miner; member=Progress
   string "Processing files"
   double 1
method call sender=:1.55 -> dest=org.freedesktop.Tracker1 serial=205 
path=/org/freedesktop/Tracker1/Resources; interface=org.freedesktop.Tracker1.Resources; 
member=SparqlQuery
   string "SELECT ?s WHERE { ?s nie:url "file:///home/meego/.recently-used.xbel.TGR7EV" }"
method call sender=:1.57 -> dest=org.freedesktop.DBus serial=220 path=/org/freedesktop/DBus;
interface=org.freedesktop.DBus; member=GetConnectionUnixProcessID
   string ":1.55"
method return sender=:1.57 -> dest=:1.55 reply_serial=205
   array [
   ]

It's possible to filter which signals/methods are reported, using watch expressions, like this example from the man page for dbus-monitor to use dbus-monitor "to watch for the gnome typing monitor to say things":

dbus-monitor "type=’signal’,sender=’org.gnome.TypingMonitor’,interface=’org.gnome.TypingMonitor’"

Interacting with a bus programatically using high-level bindings

High level bindings for D-Bus tend to provide a mechanism for proxying remote objects: so instead of having to deal with message sending directly, objects on the bus can be proxied to local objects in the application. From there, a program can interact with objects on the bus by calling methods on the proxied object.

D-Bus GLib

The D-Bus GLib bindings (yum install dbus-glib-devel) offer a high-level, GObject-like binding for interacting with the D-Bus message bus.

Below is an example of using the bindings to determine the online state of a MeeGo system using the D-Bus service (on the system bus) provided by the ConnMan connectivity daemon.

/*
 * amionline.c
 * Uses dbus-glib to ask ConnMan whether there is an active internet connection
 * Compile with:
 * gcc -o amionline amionline.c `pkg-config --libs --cflags glib-2.0 gthread-2.0 dbus-glib-1`
 */

#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>

#define CONNMAN_SERVICE           "org.moblin.connman"
#define CONNMAN_MANAGER_PATH      "/"
#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"

static	GMainLoop *main_loop;

static void
_method_call_notify_cb (DBusGProxy *proxy,
			DBusGProxyCall *call,
			gpointer user_data)
{
	GError *error = NULL;
	gchar *state = NULL;

	dbus_g_proxy_end_call (proxy,
                               call,
                               &error,
                               G_TYPE_STRING,
                               &state,
                               G_TYPE_INVALID);

	g_print ("Network state changed, it is now %s\n",
		 state);

	g_main_loop_quit (main_loop);
}

int
main (int    argc,
      char **argv)
{
	DBusGConnection *connection;
	DBusGProxy *proxy;

	main_loop = g_main_loop_new (NULL,
                                     TRUE);

	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM,
                                     NULL);
	proxy = dbus_g_proxy_new_for_name (connection,
                                           CONNMAN_SERVICE,
                                           CONNMAN_MANAGER_PATH,
                                           CONNMAN_MANAGER_INTERFACE);

	dbus_g_proxy_begin_call (proxy,
                                 "GetState",
                                 _method_call_notify_cb,
                                 main_loop,
                                 NULL,
                                 G_TYPE_INVALID);

	g_main_loop_run (main_loop);
}
Personal tools