DBus и как его изучить

Разработка на C# под linux
 
D-Bus was started in 2002, version 1.0 — considered API stable — was released in November 2006

a port for Windows exists.

2005-01-05, Robert Love, http://www.linuxjournal.com/article/7744

https://en.wikipedia.org/wiki/D-Bus


Implementations of D-Bus:
D-Bus on libdbus
GDBus (GNOME),
QtDBus (Qt/KDE),
dbus-java,
sd-bus (part of systemd)

D-BUS is an interprocess communication (IPC) system, providing a simple yet powerful mechanism allowing applications to talk to one another, communicate information and request services.
D-BUS was designed from scratch
D-BUS' initial goal is to be a replacement for CORBA and DCOP, the remote object systems used in GNOME and KDE, respectively.
D-BUS can become a unified and agnostic IPC mechanism used by both desktops, satisfying their needs and ushering in new features.
think UNIX domain sockets on steroids.

A single bus shared by the entire system allows for propagation of events, from the kernel (see The Kernel Event Layer) to the uppermost applications on the system.
Now, events such as disk full and printer queue empty or even battery power low can bubble up the system stack, available for whatever application cares, allowing the system to respond and react.

D-BUS implements a remote object system, letting one application request services and invoke methods from a different object—think CORBA without the complications.

Wire mechanism

Processes connected to a bus don't know how it is internally implemented, but D-Bus specification guarantees that every process connected to the bus is able to communicate with each other through it.

The D-Bus specification defines the wire protocol: how to build the D-Bus messages to be exchanged between processes within a D-Bus connection. But it doesn't define the underlying transport method for delivering such messages.

Как вообще работает DBus ?
libdbus is intended to be a low-level backend for the higher level bindings. Much of the libdbus API is only useful for binding implementation.
Objects are addressed using path names, such as /org/cups/printers/queue.

Messages are sent to objects.
the basic unit of IPC in D-BUS is a message, not a byte stream.
D-BUS breaks up IPC into discrete messages, complete with headers (metadata) and a payload (the data).
The message format is binary, typed, fully aligned and simple.
It is an inherent part of the wire protocol.

Processes on the message bus are associated with objects and implemented interfaces on that object.

D-BUS, however, provides a daemon, known as the message bus daemon, that routes messages between processes on a specific bus.

Applications can send to or listen for various events on the bus.

A final unique feature is the creation of not one but two of these buses, the system bus and the session bus.
The system bus is global, system-wide and runs at the system level. All users of the system can communicate over this bus with the proper permissions allowing the concept of system-wide events.
The session bus, however, is created during user login and runs at the user, or session, level.

    https://forum.kde.org/viewtopic.php?f=43&t=62126

An application can have any number of connections with the bus.
Each connection gets an unique identifier so one can send messages to a specific connection and one can check which specific connection a message came from.
Connections can optionally be associated with additional names, often referred to as "well known names", e.g. org.kde.knotify

four types of messages

There are four types of messages: method calls, method returns, errors and signals.
Method calls are sent to a specific connection, same for method returns and errors.
(theoretically all connections can see them, in reality they are filtered by a default filter in the library)
Signals are "broadcasted" to all connections.
Signals are notification that a specific event has occurred. They are simple, asynchronous, one-way heads-up messages.
The events are sent asynchronously, and without polling.
Method call messages allow an application to request the invocation of a method on a remote object.
Method return messages provide the return value resulting from a method invocation.
Error messages provide exceptions in response to a method invocation.

type system

D-BUS is fully typed and type-safe. Both a message's header and payload are fully typed. Valid types include byte, Boolean, 32-bit integer, 32-bit unsigned integer, 64-bit integer, 64-bit unsigned integer, double-precision floating point and string. A special array type allows for the grouping of types. A DICT type allows for dictionary-style key/value pairs.

Messages have a well-defined structure, even the types of the data carried in their payload are defined, allowing the bus to validate them and to reject any ill-formed message. In this regard, D-Bus is closer to an RPC mechanism than to a classic IPC mechanism, with its own type definition system and its own marshaling.

security

D-BUS is secure. It implements a simple protocol based on SASL profiles for authenticating one-to-one connections.
что такое SASL-профили?
предлагают читать секцию 4 документа ftp://ietf.org//rfc/rfc2222.txt

An administrator can control access to any interface on the bus.

D-BUS daemon

The D-BUS daemon was written from the ground up with security in mind.
In the reference implementation this role is performed by dbus-daemon, and so it is in all other implementations since no one has developed an alternative.
dbus-daemon itself is built on top of libdbus.

When a message bus daemon like dbus-daemon is used to implement a D-Bus bus, all processes that want to connect to the bus must know the bus address, the address by which a process can establish a D-Bus connection to the central message bus process.
In this scenario, the message bus daemon selects the bus address and the remainder processes must pass that value to their corresponding libdbus or equivalent libraries. dbus-daemon defines a different bus address for every bus instance it provides. These addresses are defined in the daemon's configuration files.
Two processes can use a D-Bus connection to exchange messages directly between them

https://github.com/mono/dbus-sharp

2006, https://blogs.gnome.org/tko/2006/07/27/c-and-dbus-making-development-easier-or-not/

dbus-sharp-object.png

dbus-binding-tool
takes a (hand written) XML file describing a DBus object interface and generates client and server side glue code. Combined with the C implementation this gives you a shared library you can start wrapping for C#.
dbus-binding-tool --mode=glib-server

а что, сразу на чистом C# протокол реализовать нельзя?
gapi2-parser
takes a (hand written) XML file referencing source files to parse as well as some namespace annotations and generates an XML description of the GObject(s).
The parser is a C source and header parser that produces an XML document describing the API.
gapi2-codegen
takes the output of gapi2-parser and generates C# source files.
The generator takes an XML API file as input and produces C# source files to implement the specified API.
gapi2-fixup
takes a bunch of extra (hand written) files and then customizes the generated code in wonderful ways I’m sure, but I didn’t want to go there
The fixup tool is an alteration engine to manipulate XML API files via a set of transformation rules.

GAPI overview

Зачем вообще существует GAPI-парсер?

http://www.mono-project.com/docs/gui/gtksharp/gapi/
GAPI tools are distributed with Gtk#
managed bindings to native libraries which utilize glib and GObject.
examples of libraries: Gtk, Atk, Pango, Gdk, libgnome, libgnomeui,libgnomecanvas, GtkGLArea.

dbus-send

Using dbus-send, or preferrably having gnome-vfs send the DBus message directly from the application itself, should be more efficient than loading the mono runtime just to send a few bytes down the socket.
#!/bin/sh
exec dbus-send --session --type=method_call --dest=org.gnome.LastExit /org/gnome/LastExit org.gnome.LastExit.Open string:"$1"

The echo server example appeared to be working, but mono was segfaulting when the client was trying to handle the method call response.

a different implementation was released shortly after. They cheated, there’s no GObject exposed to C# side but just a simple function for setting a callback function. On the plus side it causes much less headaches. I was also told there are better mono bindings around, waiting for commit approval somewhere.
Wrapping GObjects in C# by hand isn’t actually that hard

GObject and GBoxed

You should specify at a minimum all the public header files and the source files that contain class_init and get_type method implementations for all the public GObject and GBoxed types in the library.

Kernel Event Layer

The Kernel Event Layer is a kernel-to-user communication mechanism that uses a high-speed netlink socket to communicate asynchronously with user space.
This Kernel Event Layer was merged into the 2.6.10-rc1 kernel.
The Kernel Event Layer is tied to sysfs, the tree of kobjects that lives at /sys on modern Linux systems.
Each directory in sysfs is tied to a kobject, which is a structure in the kernel used to represent objects; sysfs is an object hierarchy exported as a filesystem.

Each Kernel Event Layer event is modeled as though it originated from a sysfs path.
Thus, the events appear as if they emit from kobjects.

This mechanism can be tied into D-BUS, allowing the kernel to send D-BUS signals
The sysfs paths are easily translatable to D-BUS paths, making the Kernel Event Layer and D-BUS a natural fit.

D-BUS API

The core D-BUS API, written in C, is rather low-level and large.
On top of this API, bindings integrate with programming languages and environments, including Glib, Python, Qt and Mono.

Using D-BUS starts with including its header:
#include <dbus/dbus.h>

GLib

the Glib bindings treat D-BUS connections as GObjects and allow messaging to integrate into the Glib mainloop.

The header file <dbus/dbus-glib.h> declares multiple functions for connecting D-BUS to the Glib mainloop.

Count of buses

1 - system session
N - a session bus for each user login session
total = 1 + N

lifetime management

bus sends a notification when a bus name is released due to a process termination.
Bus names can be used as a simple way to implement single instance applications

Unix-domain socket

Unix-domain socket are filesystem objects, and therefore they can be identified by a filename, so a valid address would be unix:path=/tmp/.hiddensocket
Both processes must pass the same address to their respective communications libraries to establish the D-Bus connection between them.
An address can also provide additional data to the communications library in the form of comma-separated key=value pairs.

Service activation

dbus-daemon improves the feature set already provided by D-Bus itself with additional functionality. For example, service activation allows to automatically start services only when they are needed —when the first request to any bus name of such service arrives to the message bus daemon.
dbus-daemon improves the feature set already provided by D-Bus itself with additional functionality. For example, service activation allows to automatically start services only when they are needed — when the first request to any bus name of such service arrives to the message bus daemon.

Usages

NetworkManager network daemon, BlueZ bluetooth stack and Pulseaudio sound server
use D-Bus to provide part or all of its services, and
systemd is promoting traditional system daemons to D-Bus services, such as logind.