Введение

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).

Модель автобуса

Каждое соединение с шиной идентифицируется в контексте D-Bus посредством так называемого имени шины. Имя шины состоит из двух или более строк, разделенных точками, содержащих буквы, цифры, дефисы и подчеркивания. Пример допустимого имени шины – . Когда процесс устанавливает соединение с шиной, шина присваивает этому соединению специальное имя шины, называемое уникальным именем соединения. Имена шин этого типа неизменяемы – гарантируется, что они не изменятся, пока существует соединение, и, что более важно, не могут быть повторно использованы в течение всего времени существования шины. Это означает, что ни одному другому соединению с этой шиной никогда не будет присвоено такое уникальное имя соединения, даже если тот же процесс закроет соединение с шиной и создаст новое. Уникальные имена соединений легко узнаваемы, поскольку они начинаются с символа двоеточия, который в противном случае запрещен. Пример уникального имени соединения – (символы после двоеточия не имеют специального значения). Процесс может запросить дополнительные имена шин для своего соединения, при условии, что запрошенное имя еще не используется другим соединением с шиной. В терминологии D-Bus, когда имя шины присваивается соединению, говорят, что соединение владеет этим именем шины. В этом смысле имя шины не может принадлежать двум соединениям одновременно, но, в отличие от уникальных имен соединений, эти имена могут быть повторно использованы, если они доступны: процесс может повторно получить имя шины, освобожденное другим процессом – намеренно или нет. Идея этих дополнительных имен шин, обычно называемых общеизвестными именами, заключается в предоставлении способа обращения к службе, используя заранее оговоренное имя шины. Например, служба, сообщающая текущее время и дату в системной шине, находится в процессе, соединение которого владеет именем шины , независимо от того, какой это процесс. Имена шин могут использоваться как простой способ реализации приложений с единственным экземпляром (вторые экземпляры обнаруживают, что имя шины уже занято). Их также можно использовать для отслеживания жизненного цикла процесса службы, поскольку шина отправляет уведомление, когда имя шины освобождается из-за завершения процесса.

Модель объекта

Из-за своей первоначальной концепции как замены нескольких компонентно-ориентированных систем связи, 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 определяет ряд административных операций шины (называемых «службами шины»), которые выполняются с использованием объекта, расположенного по имени шины. Каждая шина резервирует это специальное имя шины для себя и управляет любыми запросами, отправленными конкретно в эту комбинацию имени шины и пути объекта. Административные операции, предоставляемые шиной, определяются интерфейсом объекта. Эти операции используются, например, для предоставления информации о состоянии шины или для управления запросом и освобождением дополнительных известных имен шин.

Внутренние

Большинство существующих реализаций 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. Активация службы — важная функция, облегчающая управление жизненным циклом служб (например, когда компонент рабочего стола должен запуститься или остановиться).

История и принятие

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.