新ではsystemdにv221のリリースで、我々は導入されているSD-バスAPIをの安定版リリースに付属ことにsystemd。SD-バスは、私たちの最小限のD-バスであるIPCのCライブラリ古典的なソケットベースのD-バスとの両方のサポート、kdbusとしてバックエンドを。ライブラリはしばらくの間systemdの一部でしたが、外部ユーザーに影響を与えずにAPIを自由に変更したかったため、内部でのみ使用されていました。ただし、v221以降、安定したAPIを作成できたと確信しています。
この投稿では、sd-busライブラリの概要、D-Busの基本とその概念の簡単な要約、およびそれを使用してD-Busクライアントとサービスを作成する方法の簡単な例を示します。
D-Busとは何ですか?
D-Busが実際に何であるかを簡単に思い出させることから始めましょう。これは、Linuxおよびその他のオペレーティングシステム用の強力な汎用IPCシステムです。バス、オブジェクト、インターフェイス、メソッド、シグナル、プロパティなどの概念を定義します。きめ細かいアクセス制御、リッチタイプのシステム、簡単な検出、自己診断、監視、信頼性の高いマルチキャスト、サービスの起動、ファイル記述子の転送などを提供します。Linuxで使用されているプログラミング言語の多くにはバインディングがあります。
D-Busは、10年以上にわたってLinuxシステムのコアコンポーネントです。これは、Linuxで最も広く使用されている高レベルのローカルIPCシステムです。 systemdは、その開始以来、インターフェイスを公開するIPCシステムです。そしてsystemdの前でさえ、Upstartがそのインターフェースに使用したのはIPCシステムでした。 GNOME、KDE、および多くのシステムコンポーネントで使用されます。
D-Busは、仕様とリファレンス実装の両方を指します。リファレンス実装は、バスサーバーコンポーネントとクライアントライブラリの両方を提供します。クライアントライブラリには、C言語と他のプログラミング言語の両方で人気のある後続の実装が他にもたくさんありますが、広く使用されているサーバー側は、リファレンス実装で指定されているものだけです。 (ただし、kdbusプロジェクトは、カーネルコンポーネントとしてこのサーバー実装の代替手段を提供するように取り組んでいます。)
D-Bus IPC AF_UNIX. TCP/IP. , D-Bus TCP . D-Bus , ssh, . systemd , API .
D-Bus: , , AF_UNIX FIFO UNIX . , D-Bus -: AF_UNIX/FIFO D-Bus , TCP HTTP/REST. , AF_UNIX/FIFO , D-Bus , , , , .
10- D-Bus , , , - ( , kdbus, sd-bus), , , . IPC, , D-Bus, , , D-Bus.
: D-Bus . Linux IPC, . , D-Bus , , , .
sd-bus?
, sd-bus, D-Bus .
D-Bus: libdbus, D-Bus, GDBus, GLib, GNOME.
libdbus , . , . , API , API , . , , . , (, OOM , ) , Windows UNIX.
GDBus - . GLib/GObject libdbus. GDBus , libdbus. libdbus, , GObject D-Bus GObject. D-Bus GVariant, GLib. GLib, , D-Bus , libdbus.
sd-bus , libdbus, GDBus. libdbus GDBus: , , , , , , , GDBus/GLib/GObject/GVariant. systemd, OOM. , , kdbus D-Bus («dbus1»). , kdbus, dbus1, - , . libdbus GDBus, sd-bus, Linux Linux , . , ( ): libdbus, GDBus . ( ), . , : , kdbus , , , libdbus GDBus.
, , API :
GLib/GObject, GDBus .
, Linux, Windows, Mac OS UNIX, GDBus ( GLib/GObject), libdbus ( ).
sd-bus.
( C++, . : Qt, QtDBus API D-Bus, libdbus.)
D-Bus
D-Bus . , . . :
- , IPC. : , , ; , , , . ( , , , , , , , .)
- , IPC API . . ,
org.freedesktop.NetworkManager
- , API- NetworkManager,org.freedesktop.login1
- , API-systemd-logind
.
- , IPC API . , , , . , . .
- . , , - . - , , . , D-Bus , , . :
/org/freedesktop/login1
- «»org.freedesktop.login1
(, , systemd-logind). , . , ,systemd-logind
/org/freedesktop/login1/session
, :/org/freedesktop/login1/session/_7
,/org/freedesktop/login1/session./_55
. , .
, , . - , ( ), . D-Bus , , Java, . , . , . (, , , , .) , , , . ,
org.freedesktop.DBus.Introspectable
,org.freedesktop.DBus.Peer
org.freedesktop.DBus.Properties
.
. «» «», - , Java. D-Bus , . D-Bus . , , . ( ) CamelCase. ,
systemd-logind
ActivateSession
org.freedesktop.login1.Manager
,/org/freedesktop/login1
org.freedesktop.login1
.
, ( , , . ). , . . , ,
s
u
32- , ,as
a(sb)
, . . D-Bus, .ActivateSession
( , ,s
) ( , , ). , , . .
- , D-Bus. , . . , , . , , - . , . / --, -- ( , , --). :
systemd-logind
SessionNew
- , ,SessionRemoved
, .
- , D-Bus. , , C#. . , , . :
systemd-logind
Docked
b
( ). ,systemd-logind
, - ( ).
D-Bus . , . . , -, HTTP REST. HTTP- D-Bus:
HTTP-, . , VPN. , , . «» D-Bus.
HTTP- . .
HTTP- URL-. URL-, ( , «/») D-Bus.
«» URL- ( , , , ), , . D-Bus .
, HTTP- «?», D-Bus.
, HTTP- D-Bus . , , , .
. , , .
systemd busctl, D-Bus. , . ( --user, ):
$ busctl NAME PID PROCESS USER CONNECTION UNIT SESSION DESCRIPTION :1.1 1 systemd root :1.1 - - - :1.11 705 NetworkManager root :1.11 NetworkManager.service - - :1.14 744 gdm root :1.14 gdm.service - - :1.4 708 systemd-logind root :1.4 systemd-logind.service - - :1.7200 17563 busctl lennart :1.7200 session-1.scope 1 - […] org.freedesktop.NetworkManager 705 NetworkManager root :1.11 NetworkManager.service - - org.freedesktop.login1 708 systemd-logind root :1.4 systemd-logind.service - - org.freedesktop.systemd1 1 systemd root :1.1 - - - org.gnome.DisplayManager 744 gdm root :1.14 gdm.service - - […]
( , ).
, . , ":1.11". D-Bus . , , , . , IP-. , , busctl, . , ( ; , ). DNS, , IP- , , . , , IP-, , . ( , , , IP- , ).
, . , (, , systemd).
. , org.freedesktop.login1:
$ busctl tree org.freedesktop.login1 └─/org/freedesktop/login1 ├─/org/freedesktop/login1/seat │ ├─/org/freedesktop/login1/seat/seat0 │ └─/org/freedesktop/login1/seat/self ├─/org/freedesktop/login1/session │ ├─/org/freedesktop/login1/session/_31 │ └─/org/freedesktop/login1/session/self └─/org/freedesktop/login1/user ├─/org/freedesktop/login1/user/_1000 └─/org/freedesktop/login1/user/self
, ? , , : TAB, . D-Bus!
, . . , , , :
$ busctl introspect org.freedesktop.login1 /org/freedesktop/login1/session/_31
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
org.freedesktop.login1.Session interface - - -
.Activate method - - -
.Kill method si - -
.Lock method - - -
.PauseDeviceComplete method uu - -
.ReleaseControl method - - -
.ReleaseDevice method uu - -
.SetIdleHint method b - -
.TakeControl method b - -
.TakeDevice method uu hb -
.Terminate method - - -
.Unlock method - - -
.Active property b true emits-change
.Audit property u 1 const
.Class property s "user" const
.Desktop property s "" const
.Display property s "" const
.Id property s "1" const
.IdleHint property b true emits-change
.IdleSinceHint property t 1434494624206001 emits-change
.IdleSinceHintMonotonic property t 0 emits-change
.Leader property u 762 const
.Name property s "lennart" const
.Remote property b false const
.RemoteHost property s "" const
.RemoteUser property s "" const
.Scope property s "session-1.scope" const
.Seat property (so) "seat0" "/org/freedesktop/login1/seat... const
.Service property s "gdm-autologin" const
.State property s "active" -
.TTY property s "/dev/tty1" const
.Timestamp property t 1434494630344367 const
.TimestampMonotonic property t 34814579 const
.Type property s "x11" const
.User property (uo) 1000 "/org/freedesktop/login1/user/_1... const
.VTNr property u 1 const
.Lock signal - - -
.PauseDevice signal uus - -
.ResumeDevice signal uuh - -
.Unlock signal - - -
, busctl , , TAB. , , , systemd-logind
. , . . . , . . .
. : - :
# busctl call org.freedesktop.login1 /org/freedesktop/login1/session/_31 org.freedesktop.login1.Session Lock
, , : . - , - , TAB. Lock
, . , , Enter , ( , systemd-logind. GNOME , KDE ).
Lock
, . , . , systemd :
# busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartUnit ss "cups.service" "replace"
o "/org/freedesktop/systemd1/job/42684"
, , ( , , ). - . , , . StartUnit systemd , , . . , : ( o ), .
busctl
. , D-Bus ( .cap
Wireshark!) . , sd-bus, busctl
, , .
busctl
( ) API sd-bus. , sd-bus. , . kdbus, D-Bus, !
sd-bus
! , sd-bus.
API sd-bus sd-bus.h.
, .
kdbus, dbus1 .
ssh .
. 34 , PID .
, , , .
, , .
D-Bus UNIX ( ), D-Bus Linux.
, . .
sd-bus
. :
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
int main(int argc, char *argv[]) {
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *m = NULL;
sd_bus *bus = NULL;
const char *path;
int r;
/* Connect to the system bus */
r = sd_bus_open_system(&bus);
if (r < 0) {
fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
goto finish;
}
/* Issue the method call and store the respons message in m */
r = sd_bus_call_method(bus,
"org.freedesktop.systemd1", /* service to contact */
"/org/freedesktop/systemd1", /* object path */
"org.freedesktop.systemd1.Manager", /* interface name */
"StartUnit", /* method name */
&error, /* object to return error in */
&m, /* return message on success */
"ss", /* input signature */
"cups.service", /* first argument */
"replace"); /* second argument */
if (r < 0) {
fprintf(stderr, "Failed to issue method call: %s\n", error.message);
goto finish;
}
/* Parse the response message */
r = sd_bus_message_read(m, "o", &path);
if (r < 0) {
fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
goto finish;
}
printf("Queued service job as %s.\n", path);
finish:
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_unref(bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
bus-client.c
, :
$ gcc bus-client.c -o bus-client `pkg-config --cflags --libs libsystemd`
bus-client
, . root, StartUnit
:
# ./bus-client
Queued service job as /org/freedesktop/systemd1/job/3586.
. , . busctl
, . , . , D-Bus sd-bus. , , , sd-bus.
sd-bus
, - . , . . , : 64- , 64- .
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <systemd/sd-bus.h>
static int method_multiply(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int64_t x, y;
int r;
/* Read the parameters */
r = sd_bus_message_read(m, "xx", &x, &y);
if (r < 0) {
fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
return r;
}
/* Reply with the response */
return sd_bus_reply_method_return(m, "x", x * y);
}
static int method_divide(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int64_t x, y;
int r;
/* Read the parameters */
r = sd_bus_message_read(m, "xx", &x, &y);
if (r < 0) {
fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
return r;
}
/* Return an error on division by zero */
if (y == 0) {
sd_bus_error_set_const(ret_error, "net.poettering.DivisionByZero", "Sorry, can't allow division by zero.");
return -EINVAL;
}
return sd_bus_reply_method_return(m, "x", x / y);
}
/* The vtable of our little object, implements the net.poettering.Calculator interface */
static const sd_bus_vtable calculator_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("Multiply", "xx", "x", method_multiply, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Divide", "xx", "x", method_divide, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
int main(int argc, char *argv[]) {
sd_bus_slot *slot = NULL;
sd_bus *bus = NULL;
int r;
/* Connect to the user bus this time */
r = sd_bus_open_user(&bus);
if (r < 0) {
fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
goto finish;
}
/* Install the object */
r = sd_bus_add_object_vtable(bus,
&slot,
"/net/poettering/Calculator", /* object path */
"net.poettering.Calculator", /* interface name */
calculator_vtable,
NULL);
if (r < 0) {
fprintf(stderr, "Failed to issue method call: %s\n", strerror(-r));
goto finish;
}
/* Take a well-known service name so that clients can find us */
r = sd_bus_request_name(bus, "net.poettering.Calculator", 0);
if (r < 0) {
fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
goto finish;
}
for (;;) {
/* Process requests */
r = sd_bus_process(bus, NULL);
if (r < 0) {
fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
goto finish;
}
if (r > 0) /* we processed a request, try to process another one, right-away */
continue;
/* Wait for the next request to process */
r = sd_bus_wait(bus, (uint64_t) -1);
if (r < 0) {
fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
goto finish;
}
}
finish:
sd_bus_slot_unref(slot);
sd_bus_unref(bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
bus-service.c
, :
$ gcc bus-service.c -o bus-service `pkg-config --cflags --libs libsystemd`
:
$ ./bus-service
. , , , . : , . : , , , . , --user busctl. .
$ busctl --user tree net.poettering.Calculator └─/net/poettering/Calculator
, , , , . , :
$ busctl --user introspect net.poettering.Calculator /net/poettering/Calculator NAME TYPE SIGNATURE RESULT/VALUE FLAGS net.poettering.Calculator interface - - - .Divide method xx x - .Multiply method xx x - org.freedesktop.DBus.Introspectable interface - - - .Introspect method - s - org.freedesktop.DBus.Peer interface - - - .GetMachineId method - s - .Ping method - - - org.freedesktop.DBus.Properties interface - - - .Get method ss v - .GetAll method s a{sv} - .Set method ssv - - .PropertiesChanged signal sa{sv}as - -
, sd-bus . , , , ! , «xx» ( 64- ) «x». ! ?
$ busctl --user call net.poettering.Calculator /net/poettering/Calculator net.poettering.Calculator Multiply xx 5 7 x 35
! 5 7, 35! :
$ busctl --user call net.poettering.Calculator /net/poettering/Calculator net.poettering.Calculator Divide xx 99 17 x 5
! ! ! :
$ busctl --user call net.poettering.Calculator /net/poettering/Calculator net.poettering.Calculator Divide xx 43 0
Sorry, can't allow division by zero.
! . , , .
, . , , , , , . D-Bus sd-bus, ...
この投稿がお役に立てば幸いです。自分のプログラムにsd-busを使用することに興味がある場合は、それがお役に立てば幸いです。さらに質問がある場合は、(不完全な)manページを見て、IRCまたはsystemdメーリングリストで質問してください。さらに例が必要な場合は、systemdのソースツリーを見てください。systemdの多くのバスサービスはすべて、sd-busを広範囲に使用しています。