Введение
Linux middleware
D-Bus (сокращение от "Desktop Bus") — это механизм обмена сообщениями, позволяющий осуществлять взаимодействие между несколькими процессами, выполняющимися одновременно на одном компьютере. D-Bus был разработан в рамках проекта freedesktop.org, инициированного разработчиком GNOME Хавоком Пеннингтоном для стандартизации служб, предоставляемых Linux-окружениями рабочего стола, такими как GNOME и KDE. Проект freedesktop.org также разработал свободную библиотеку программного обеспечения с открытым исходным кодом под названием libdbus, как эталонную реализацию спецификации. Эту библиотеку не следует путать с самим D-Bus, поскольку существуют и другие реализации спецификации D-Bus, такие как GDBus (GNOME), QtDBus (Qt/KDE), dbus-java и sd-bus (часть systemd).
is a message oriented middleware mechanism that allows communication between multiple processes running concurrently on the same machine. D Bus was developed as part of the freedesktop. org project, initiated by GNOME developer Havoc Pennington to standardize services provided by Linux desktop environments such as GNOME and KDE. The freedesktop. org project also developed a free and open source software library called libdbus, as a reference implementation of the specification. This library should not be confused with D Bus itself, as other implementations of the D Bus specification also exist, such as GDBus (GNOME), QtDBus (Qt/KDE), dbus java and sd bus (part of systemd).
Модель автобуса
Каждое соединение с шиной идентифицируется в контексте D-Bus посредством так называемого имени шины. Имя шины состоит из двух или более строк, разделенных точками, содержащих буквы, цифры, дефисы и подчеркивания. Пример допустимого имени шины – . Когда процесс устанавливает соединение с шиной, шина присваивает этому соединению специальное имя шины, называемое уникальным именем соединения. Имена шин этого типа неизменяемы – гарантируется, что они не изменятся, пока существует соединение, и, что более важно, не могут быть повторно использованы в течение всего времени существования шины. Это означает, что ни одному другому соединению с этой шиной никогда не будет присвоено такое уникальное имя соединения, даже если тот же процесс закроет соединение с шиной и создаст новое. Уникальные имена соединений легко узнаваемы, поскольку они начинаются с символа двоеточия, который в противном случае запрещен. Пример уникального имени соединения – (символы после двоеточия не имеют специального значения). Процесс может запросить дополнительные имена шин для своего соединения, при условии, что запрошенное имя еще не используется другим соединением с шиной. В терминологии D-Bus, когда имя шины присваивается соединению, говорят, что соединение владеет этим именем шины. В этом смысле имя шины не может принадлежать двум соединениям одновременно, но, в отличие от уникальных имен соединений, эти имена могут быть повторно использованы, если они доступны: процесс может повторно получить имя шины, освобожденное другим процессом – намеренно или нет. Идея этих дополнительных имен шин, обычно называемых общеизвестными именами, заключается в предоставлении способа обращения к службе, используя заранее оговоренное имя шины. Например, служба, сообщающая текущее время и дату в системной шине, находится в процессе, соединение которого владеет именем шины , независимо от того, какой это процесс. Имена шин могут использоваться как простой способ реализации приложений с единственным экземпляром (вторые экземпляры обнаруживают, что имя шины уже занято). Их также можно использовать для отслеживания жизненного цикла процесса службы, поскольку шина отправляет уведомление, когда имя шины освобождается из-за завершения процесса.
When a process sets up a connection to a bus, the bus assigns to the connection a special bus name called unique connection name. Bus names of this type are immutable—it is guaranteed they will not change as long as the connection exists—and, more importantly, they cannot be reused during the bus lifetime. This means that no other connection to that bus will ever have assigned such unique connection name, even if the same process closes down the connection to the bus and creates a new one. Unique connection names are easily recognizable because they start with the otherwise forbidden colon character. An example of a unique connection name is (the characters after the colon have no particular meaning). A process can ask for additional bus names for its connection, provided that any requested name is not already being used by another connection to the bus. In D Bus parlance, when a bus name is assigned to a connection, it is said the connection owns the bus name. In that sense, a bus name cannot be owned by two connections at the same time, but, unlike unique connection names, these names can be reused if they are available: a process may reclaim a bus name released—purposely or not—by another process. The idea behind these additional bus names, commonly called well known names, is to provide a way to refer to a service using a prearranged bus name. For instance, the service that reports the current time and date in the system bus lies in the process whose connection owns the bus name, regardless of which process it is. Bus names can be used as a simple way to implement single instance applications (second instances detect that the bus name is already taken). It can also be used to track a service process lifecycle, since the bus sends a notification when a bus name is released due to a process termination.
Модель объекта
Из-за своей первоначальной концепции как замены нескольких компонентно-ориентированных систем связи, D-Bus разделяет с предшественниками объектную модель, в которой выражается семантика взаимодействия между клиентами и службами. Термины, используемые в объектной модели D-Bus, имитируют термины, используемые некоторыми объектно-ориентированными языками программирования. Это не означает, что D-Bus каким-либо образом ограничен языками ООП; на самом деле, наиболее распространенная реализация написана на C — процедурном языке программирования. В D-Bus процесс предоставляет свои услуги, экспонируя объекты. Эти объекты имеют методы, которые могут быть вызваны, и сигналы, которые объект может излучать. Методы и сигналы в совокупности называются членами объекта. Любой клиент, подключенный к шине, может взаимодействовать с объектом, используя его методы, отправляя запросы или отдавая команды объекту для выполнения действий. Например, объект, представляющий службу времени, может быть запрошен клиентом с помощью метода, возвращающего текущую дату и время. Клиент также может прослушивать сигналы, которые объект испускает при изменении его состояния из-за определенных событий, обычно связанных с базовой службой. Примером может служить ситуация, когда служба, управляющая аппаратными устройствами, такими как USB или сетевые драйверы, сигнализирует о событии «добавлено новое аппаратное устройство». Клиенты должны сообщить шине, что они заинтересованы в получении определенных сигналов от конкретного объекта, поскольку шина D-Bus передает сигналы только тем процессам, у которых есть зарегистрированный интерес к ним. Процесс, подключенный к шине D-Bus, может запросить экспорт любого количества объектов D-Bus. Каждый объект идентифицируется путем объекта — строкой, состоящей из цифр, букв и подчеркиваний, разделенных и начинающихся с символа косой черты, названной так из-за сходства с путями файловой системы Unix. Путь объекта выбирается запрашивающим процессом и должен быть уникальным в контексте этого шинного соединения. Примером допустимого пути объекта является Однако не требуется, но и не препятствуется, формировать иерархии внутри путей объектов. Конкретное соглашение об именовании объектов службы полностью зависит от разработчиков этой службы, но многие разработчики предпочитают использовать пространство имен, используя зарезервированное доменное имя проекта в качестве префикса (например, ). Каждый объект неразрывно связан с конкретным шинным соединением, в котором он был экспортирован, и, с точки зрения D-Bus, существует только в контексте этого соединения. Поэтому, чтобы использовать определенную службу, клиент должен указать не только путь объекта, предоставляющего требуемую службу, но и имя шины, под которым процесс службы подключен к шине. Это, в свою очередь, позволяет нескольким процессам, подключенным к шине, однозначно экспортировать различные объекты с идентичными путями объектов. Интерфейс определяет члены — методы и сигналы, которые можно использовать с объектом. Это набор объявлений методов (включая входящие и возвращаемые параметры) и сигналов (включая их параметры), идентифицируемых именем, разделенным точкой, напоминающим обозначение интерфейсов языка Java. Примером допустимого имени интерфейса является Несмотря на сходство, имена интерфейсов и имена шин не следует путать. Объект D-Bus может реализовывать несколько интерфейсов, но должен реализовать хотя бы один, обеспечивая поддержку каждого метода и сигнала, определенного в нем. Совокупность всех интерфейсов, реализованных объектом, называется типом объекта. При использовании объекта клиенту рекомендуется указывать имя интерфейса члена вместе с именем члена, но это обязательно только в случае неоднозначности, вызванной дублированием имен членов, доступных из разных интерфейсов, реализованных объектом; в противном случае выбранный член не определен или неверен. С другой стороны, испускаемый сигнал всегда должен указывать, к какому интерфейсу он принадлежит. Спецификация D-Bus также определяет несколько стандартных интерфейсов, которые объекты могут реализовать в дополнение к своим собственным интерфейсам. Хотя технически это необязательно, большинство разработчиков служб D-Bus предпочитают поддерживать их в экспортируемых объектах, поскольку они предлагают важные дополнительные функции клиентам D-Bus, такие как интроспекция. Эти стандартные интерфейсы:
: предоставляет способ проверки, активно ли шинное соединение D-Bus. : предоставляет механизм интроспекции, с помощью которого клиентский процесс может во время выполнения получить описание (в формате XML) интерфейсов, методов и сигналов, которые реализует объект. : позволяет объекту D-Bus экспонировать базовые свойства или атрибуты исходного объекта или эмулировать их, если они не существуют. : когда служба D-Bus организует свои объекты иерархически, этот интерфейс предоставляет способ запросить у объекта все под-объекты по его пути, а также их интерфейсы и свойства, используя один вызов метода. Спецификация D-Bus определяет ряд административных операций шины (называемых «службами шины»), которые выполняются с использованием объекта, расположенного по имени шины. Каждая шина резервирует это специальное имя шины для себя и управляет любыми запросами, отправленными конкретно в эту комбинацию имени шины и пути объекта. Административные операции, предоставляемые шиной, определяются интерфейсом объекта. Эти операции используются, например, для предоставления информации о состоянии шины или для управления запросом и освобождением дополнительных известных имен шин.
: provides a way to test if a D Bus connection is alive. : provides an introspection mechanism by which a client process can, at run time, get a description (in XML format) of the interfaces, methods and signals that the object implements. : allows a D Bus object to expose the underlying native object properties or attributes, or simulate them if it does not exist. : when a D Bus service arranges its objects hierarchically, this interface provides a way to query an object about all sub objects under its path, as well as their interfaces and properties, using a single method call. The D Bus specification defines a number of administrative bus operations (called "bus services") to be performed using the object that resides in the bus name. Each bus reserves this special bus name for itself, and manages any requests made specifically to this combination of bus name and object path. The administrative operations provided by the bus are those defined by the object's interface These operations are used for example to provide information about the status of the bus, or to manage the request and release of additional well known bus names.
Внутренние
Большинство существующих реализаций D-Bus следуют архитектуре эталонной реализации. Эта архитектура состоит из двух основных компонентов:
библиотеки коммуникаций типа «точка-точка», реализующей протокол D-Bus для обмена сообщениями между двумя процессами. В эталонной реализации эта библиотека может быть обернута другой библиотекой более высокого уровня, языковой привязкой или полностью заменена другой автономной реализацией, выполняющей ту же функцию. Эта библиотека поддерживает только коммуникацию один-к-одному между двумя процессами. специальный процесс-демон, выполняющий роль шины, к которому остальные процессы подключаются, используя любую библиотеку коммуникаций D-Bus. Этот процесс также известен как демон шины сообщений, поскольку он отвечает за маршрутизацию сообщений от любого процесса, подключенного к шине, к другому. В эталонной реализации эту роль выполняет , которая сама построена на основе Другая реализация демона шины сообщений — , построенная на основе библиотека (или её эквивалент) внутри использует собственный механизм межпроцессного взаимодействия (IPC) нижнего уровня для передачи необходимых сообщений D-Bus между двумя процессами на обоих концах соединения D-Bus. Спецификация D-Bus не предписывает, какие конкретно механизмы IPC должны быть доступны, поскольку библиотека коммуникаций сама решает, какие методы транспортировки она поддерживает. Например, в Unix-подобных операционных системах, таких как Linux, обычно используются сокеты домена Unix в качестве базового метода транспортировки, но также поддерживаются и TCP-сокеты. Библиотеки коммуникаций обоих процессов должны согласовать выбранный метод транспортировки, а также конкретный канал, используемый для их связи. Эта информация определяется тем, что D-Bus называет адресом. Сокеты домена Unix являются объектами файловой системы и, следовательно, могут быть идентифицированы по имени файла, поэтому допустимым адресом будет unix:path=/tmp/.hidden_socket. Оба процесса должны передать один и тот же адрес в свои соответствующие библиотеки коммуникаций для установления соединения D-Bus между ними. Адрес также может предоставлять дополнительные данные библиотеке коммуникаций в виде пар ключ=значение, разделенных запятыми. Таким образом, например, он может предоставлять информацию об аутентификации для конкретного типа соединения, который её поддерживает. Когда для реализации шины D-Bus используется демон шины сообщений, все процессы, желающие подключиться к шине, должны знать адрес шины — адрес, по которому процесс может установить соединение D-Bus с центральным процессом демона шины сообщений. В этом сценарии демон шины сообщений выбирает адрес шины, а остальные процессы должны передать это значение в соответствующие или эквивалентные библиотеки. определяет различный адрес шины для каждого экземпляра шины, который он предоставляет. Эти адреса определены в файлах конфигурации демона. Два процесса могут использовать соединение D-Bus для обмена сообщениями напрямую между собой, но это не типичный способ использования D-Bus. Обычно используется демон шины сообщений (например,) в качестве центральной точки связи, к которой каждый процесс должен установить своё соединение D-Bus. Когда процесс — клиент или служба — отправляет сообщение D-Bus, процесс демона шины сообщений получает его первым и доставляет соответствующему получателю. Демон шины сообщений можно рассматривать как концентратор или маршрутизатор, отвечающий за доставку каждого сообщения к месту назначения путем его повторной отправки через соединение D-Bus процессу-получателю. Процесс получателя определяется именем шины назначения в заголовке сообщения или информацией о подписке на сигналы, поддерживаемой демоном шины сообщений в случае сообщений о распространении сигналов. Демон шины сообщений также может генерировать собственные сообщения в ответ на определенные условия, например, сообщение об ошибке процессу, отправившему сообщение в несуществующее имя шины. расширяет набор функций, уже предоставляемых самим D-Bus, добавляя дополнительную функциональность. Например, активация службы позволяет автоматически запускать службы по мере необходимости — когда первый запрос на любое имя шины этой службы поступает в демон шины сообщений. Таким образом, сервисные процессы не нужно запускать во время инициализации системы или пользователя и не нужно, чтобы они потребляли память или другие ресурсы, когда они не используются. Эта функция изначально была реализована с помощью setuid-помощников, но в настоящее время её также может предоставлять фреймворк активации служб systemd. Активация службы — важная функция, облегчающая управление жизненным циклом служб (например, когда компонент рабочего стола должен запуститься или остановиться).
The library (or its equivalent) internally uses a native lower level IPC mechanism to transport the required D Bus messages between the two processes in both ends of the D Bus connection. D Bus specification does not mandate which particular IPC transport mechanisms should be available to use, as it is the communications library that decides what transport methods it supports. For instance, in Unix like operating systems such as Linux typically uses Unix domain sockets as the underlying transport method, but it also supports TCP sockets. The communications libraries of both processes must agree on the selected transport method and also on the particular channel used for their communication. This information is defined by what D Bus calls an address. Unix domain sockets 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. This way, for example, it can provide authentication information to a specific type of connection that supports it. When a message bus daemon like 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 or equivalent libraries. 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, but this is not the way in which D Bus is normally intended to be used. The usual way is to always use a message bus daemon (i. e. ) as a communications central point to which each process should establish its point to point D Bus connection. When a process—client or service—sends a D Bus message, the message bus process receives it in the first instance and delivers it to the appropriate recipient. The message bus daemon may be seen as a hub or router in charge of getting each message to its destination by repeating it through the D Bus connection to the recipient process. The recipient process is determined by the destination bus name in the message's header field, or by the subscription information to signals maintained by the message bus daemon in the case of signal propagation messages. The message bus daemon can also produce its own messages as a response to certain conditions, such as an error message to a process that sent a message to a nonexistent bus name. improves the feature set already provided by D Bus itself with additional functionality. For example, service activation allows automatic starting of services when needed—when the first request to any bus name of such service arrives at the message bus daemon. This way, service processes neither need to be launched during the system initialization or user initialization stage nor need they consume memory or other resources when not being used. This feature was originally implemented using setuid helpers, but nowadays it can also be provided by systemd's service activation framework. Service activation is an important feature that facilitates the management of the process lifecycle of services (for example when a desktop component should start or stop).
История и принятие
D Bus был создан в 2002 году Havoc Pennington, Алексом Ларссоном (Red Hat) и Андерсом Карлссоном. Версия 1.0, считающаяся стабильной по API, была выпущена в ноябре 2006 года. Находясь под сильным влиянием системы DCOP, использовавшейся в версиях 2 и 3 KDE, D Bus заменил DCOP в выпуске KDE 4. Реализация D Bus поддерживает большинство операционных систем, соответствующих стандарту POSIX, и существует порт для Windows. Он используется Qt 4 и последующими версиями GNOME. В GNOME он постепенно заменил большинство компонентов более раннего механизма Bonobo. Он также используется Xfce. Одним из первых пользователей был (в настоящее время устаревший) слой аппаратной абстракции. HAL использовал D Bus для экспорта информации об аппаратном обеспечении, которое было добавлено или удалено с компьютера. Область применения D Bus постоянно расширяется за пределы первоначальной сферы настольных сред, охватывая всё большее количество системных служб. Например, сетевой демон NetworkManager, стек Bluetooth BlueZ и звуковой сервер PulseAudio используют D Bus для предоставления части или всех своих функций. systemd использует протокол обмена данными D Bus для связи между системой и самим systemd, а также переводит традиционные системные демоны в D Bus-сервисы, такие как logind. Polkit также является одним из основных пользователей D Bus, его демон управления политиками реализован как служба, подключенная к системной шине.
Либдбус
Хотя существует несколько реализаций D-Bus, наиболее широко используемой является эталонная реализация libdbus, разработанная тем же проектом freedesktop.org, который разработал спецификацию. Однако libdbus – это реализация низкого уровня, которая изначально не предназначалась для непосредственного использования разработчиками приложений, а скорее как справочное руководство для других реализаций D-Bus (например, тех, что включены в стандартные библиотеки окружений рабочего стола или в привязки для языков программирования). Сам проект freedesktop.org рекомендует разработчикам приложений использовать одну из привязок или реализаций более высокого уровня. Преобладание libdbus как наиболее используемой реализации D-Bus привело к тому, что термины "D-Bus" и "libdbus" часто стали использоваться как взаимозаменяемые, что вызывает путаницу.
GDBus
GDBus — это реализация D-Bus, основанная на потоках GIO, входящих в GLib, и предназначенная для использования в GTK+ и GNOME. GDBus не является надстройкой над libdbus, а представляет собой полную и независимую повторную реализацию спецификации и протокола D-Bus. MATE Desktop и Xfce (версия 4.14), также основанные на GTK+ 3, также используют GDBus.
sd-автобус
В 2013 году проект systemd переписал libdbus, стремясь упростить код, но это также привело к значительному увеличению общей производительности D-Bus. В предварительных тестах производительности BMW обнаружила, что библиотека D-Bus от systemd увеличила производительность на 360%. К версии 221 systemd API sd-bus был объявлен стабильным.
kdbus (всего один)
kdbus был проектом, целью которого являлась переработка D-Bus в механизм межпроцессного взаимодействия типа "одноранговый", опосредованный ядром. Помимо повышения производительности, kdbus должен был обладать преимуществами, вытекающими из других возможностей ядра Linux, таких как пространства имен и аудит, безопасностью благодаря посредничеству ядра, устранением гонок данных и возможностью использования D-Bus во время загрузки и завершения работы системы (как это необходимо systemd). Включение kdbus в ядро Linux оказалось спорным и было отклонено в пользу BUS1, как более универсального механизма межпроцессного взаимодействия.
Языковые связи
Было разработано несколько привязок языков программирования к D-Bus, таких как Java, C#, Ruby, Rust и Perl.