Contents |
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.
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.)
There are actually multiple D-Bus message buses running on MeeGo (and on your average Linux system) at any one time, of two types:
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:
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.
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.
Often the easiest way to get started investigating a service on the Bus is to use D-Feet, a graphical 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
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. The address to enter depends on the bus type you want to monitor:
unix:path=/var/run/dbus/system_bus_socket. You can find the system bus path by grepping /etc/dbus-1/system.conf for the <listen> setting.$env | grep DBUS_SESSION_BUS_ADDRESS
Example output:
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-6H89TrarMk,guid=a72013b7b9456e7a3eca017100000038You need the bit after the first '=' sign (starting
unix:abstract).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.
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 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);
}