Lxf99 d-bus

D-Bus: шини для вашого Linux

Вже встигли подумати про зимову гуму або переломах і вивихах? Повертайтеся назад у віртуальний світ - Андрій Боровський має на увазі шину для обміну даними між настільними додатками!

Що таке D-Bus? Найпростіша відповідь - ще одна система взаємодії між процесами (Interprocess Communication або IPC). Ключові слова тут «ще одна». Високорівневих систем IPC для Unix / Linux існує багато. Крім систем високого рівня Unix має розвинені засоби IPC низького рівня (сокети, канали), якісь успішно використовуються багатьма додатками прямо. Навіщо тоді нам може знадобитися D-Bus? Ця система замишлялася групою FreeDesktop.org як засіб IPC, яке залежить від типу робочого столу, покликану замінити як DCOP в KDE, так і CORBA / Bonobo в GNOME. Витіснити рідні кошти IPC KDE та GNOME новій системі поки не вдалося [правда, в KDE 4 D-Bus все-таки буде використовуватися замість DCOP, - прим. ред. ], Але в процесі розробки D-Bus знайшла кілька унікальних і корисних особливостей. Важливими відмітними рисами D-Bus є система сигналів і асинхронних викликів методів, а також система управління виконанням програм. Таким чином, відповідь на питання, навіщо вам може знадобитися програмування D-Bus, складається з двох частин. По-перше, багато важливі програми і системні компоненти (наприклад, Linux HAL і NetworkManager) використовують D-Bus як засіб спілкування із зовнішнім світом. По-друге, D-Bus - це переносних незалежна система IPC, яка присутня практично в кожному дистрибутиві Linux і встановлюється за умовчанням в багатьох з них. Тому, якщо ви пишете програму, яку має надавати сервіси IPC, яка є частиною будь-якого робочого столу, вам, безумовно, має сенс звернути увагу на D-Bus. При цьому слід враховувати і мінуси D-Bus. В системі все ще не реалізована зв'язок між різними машинами, хоча робота в цьому напрямку ведеться. D-Bus легко може бути перенесена на інші Unix-платформи, але її версія для Windows як і раніше далека від завершення.

Серед конкуруючих технологій (в тому сенсі, що їх часто можна використовувати замість D-Bus), слід зазначити CORBA, SOAP, XML-RPC, DCOM, DCOP, Bonobo. Чим D-Bus відрізняється від них? CORBA, як і D-Bus, використовує швидкий бінарний протокол. На відміну від D-Bus, CORBA призначається для вирішення надзвичайно широкого кола завдань і може використовуватися як в локальній, так і в розподіленої системі. В CORBA відсутні такі елементи D-Bus, як система управління виконанням програм та система сигналів. SOAP і XML-RPC є протоколи, в яких на низькому рівні активно використовується XML. Ці технології взаємодії між процесами добре підходять для Інтернету, однак при обміні даними між додатками, що працюють на одній машині, використання механізмів XML призводить до марної трати ресурсів (при цьому треба відзначити, звичайно, що функції, які залежать ці протоколи, надзвичайно легко масштабуються). Технології DCOM, DCOP і Bonobo мають один подібний недолік - кожна з них призначена для конкретної платформи (Windows, KDE та GNOME відповідно), і організувати взаємодію між додатками різних платформ з їх допомогою буде вельми непросто.

D-Bus інтерфейс клієнта Skype

Ви вже помітили, що в якості прикладу додатки, що надає послуги D-Bus, ми згадуємо клієнт Skype. Інтерфейс, що експортується клієнтом Skype дуже простий, і в той же час демонструє всі основні можливості D-Bus. Об'єкт / com / Skype підтримує один-єдиний метод - Invoke. дозволяє зовнішньому додатком передавати команди клієнту Skype. Єдиним аргументом методу Invoke є рядок команди, а повертається значенням - рядок, в якій міститься відповідь програми на передану команду. Однак клієнт Skype може не тільки виконувати команди сторонніх додатків, але і передавати їм різну інформацію, наприклад, про підключення нового користувача. Щоб отримувати повідомлення від клієнта Skype. додаток повинен зареєструвати клас / com / Skype / Client. Коли клієнт Skype хоче проінформувати додаток про що-небудь, він викликає метод Notify класу / com / Skype / Client. передаючи в єдиному параметрі цього методу рядок-повідомлення. Метод Notify не повертає значень.

Трохи про архітектуру

В основі структури D-Bus лежить поняття шини (bus). Шина являє собою механізм, за допомогою якого процеси обмінюються даними. Хоча, в принципі, будь-які два процеси можуть організувати «приватну» шину засобами D-Bus і обмінюватися даними між собою, інтерес представляють загальнодоступні шини, які підтримує демон D-Bus. Виконуваний файл демона має ім'я dbus-daemon. Зазвичай, якщо демон D-Bus доводиться запускати вручну, використовується команда dbus-launch.

Демон D-Bus надає нам дві шини: системну шину (system bus) і призначену для користувача шину (session-bus). Системна шина може використовуватися для передачі даних в масштабах системи, в той час як для користувача шина дозволяє передавати дані між процесами, які належать одному користувачеві. Слід врахувати, що D-Bus стежить за правами користувачів в системі і не дозволить вам порушити політику безпеки Linux за допомогою системної шини.

Всі процеси, що використовують D-Bus для обміну даними, виступають в ролі клієнтів, які підключаються до демона D-Bus і, таким чином, отримують доступ до однієї з шин. Про це необхідно пам'ятати, між іншим, і для того, щоб не заплутатися в термінології. Підключаючись до шини, кожен процес створює з'єднання (з демоном D-Bus). У кожного з'єднання є ім'я (яке в оригінальній літературі позначається термінами connection name і bus name). Імена з'єднань схожі на імена інтернет-вузлів, вивернуті навиворіт. Наприклад, менеджер HAL створює з'єднання з ім'ям org.freedesktop.Hal. а клієнт Skype - з ім'ям com.Skype.API. Оскільки всі функції, які залежать системну або призначену для користувача шини D-Bus, з'єднуються з демоном D-Bus, а не один з одним, існує можливість використовувати одне з'єднання D-Bus для обміну даними між різними додатками.

Якщо ми піднімемося вище на один рівень абстракції, то побачимо, в чому полягає схожість між об'єктами D-Bus та об'єктами ООП. Обмін повідомленнями в моделі «запит-відповідь» можна розглядати як виклик методу об'єкта, в якому повідомлення-запит передає параметри методу, а повідомлення-відповідь - повернені значення. Саме семантика виклику методів використовується при формуванні повідомлень-запитів та отриманні відповідей D-Bus.

Оскільки в основі викликів методів об'єктів D-Bus лежить обмін повідомленнями, існує можливість асинхронного виклику. Викликавши метод об'єкта D-Bus, програма може виконати якісь операції, не чекаючи отримання відповіді. Можна навіть викликати ще один метод об'єкта до того, як був отриманий результат попереднього виклику. Повідомлення-сигнали найпростіше порівняти з сигналами Qt.

Lxf99 d-bus

Хоча ви і не можете працювати з об'єктами D-Bus безпосередньо, система надає програмістам об'ектоподобний інтерфейс, який реалізується за допомогою так званих проксі-об'єктів (proxy objects). Проксі можна вважати представником об'єкта D-Bus у вашій програмі. Наскільки проксі-об'єкт схожий на «справжній» - залежить від реалізації. У мовах Java і Python робота з проксі здійснюється практично так само, як з «справжніми» об'єктами мови. При використанні інтерфейсів бібліотеки GLib для роботи з проксі застосовується спеціальний набір функцій.

Звертаючись до об'єктів D-Bus будь-якої програми, ви припускаєте, що хоча б один екземпляр цього додатка запущений в системі. А що, якщо це не так? Вище зазначалося, що система D-Bus здатна управляти виконанням програми. Демон D-Bus може запустити додаток на вашу вимогу (для цього, звичайно, цей додаток має бути особливим чином зареєстровано в системі). Цей механізм відомий під ім'ям D-Bus Activation.

Підключайтеся!

Основу низкоуровневого D-Bus API складають два об'єкти - DBusConnection і DBusMessage. Перший об'єкт інкапсулює все, що пов'язано з управлінням шиною D-Bus, другий дозволяє керувати повідомленнями. Ще раз нагадаю, що коли ми говоримо про об'єкти D-Bus API, мова йде не про об'єкти в сенсі ООП, а про об'єкти в стилі GTK + API (інтерфейс програмування D-Bus взагалі дуже схожий на інтерфейс програмування GTK +).

Наступний код є мінімальною програму, яка використовує можливості D-BUS.

Після того як з'єднання з шиною встановлено, ми викликаємо метод об'єкта іншої програми. Виклик методу складається з чотирьох етапів: створення повідомлення-запиту, створення списку аргументів для викликається методу, передачі повідомлення і обробки результату виклику.

Повідомлення-запит на виклик методу створюється функцією dbus_message_new_method_call (). Її чотирма аргументами є імена з'єднання віддаленого програми, об'єкта, інтерфейсу і викликається методу відповідно. Функція повертає покажчик на створений нею об'єкт DBusMessage. який містить інформацію про новий виклик. Оскільки створюване повідомлення призначене для виклику методу, ми повинні сформувати список його аргументів. Це робиться за допомогою функції dbus_message_append_args (). Перший аргумент цієї функції - покажчик на об'єкт DBusMessage. Далі слід змінне число параметрів, які передають аргументи викликається методу. Кожному аргументу відповідають два параметра функції dbus_message_append_args (). У першому параметрі передається константа, яка вказує тип аргументу, у другому - покажчик на область пам'яті, в якій зберігається його значення. Завершується список аргументів константою DBUS_TYPE_INVALID. Оскільки у викликається нами методу Invoke один параметр, ми передаємо dbus_message_append_args () список з трьох аргументів. Аргумент DBUS_TYPE_STRING вказує тип параметра Invoke. потім слід покажчик на значення (в нашому випадку - покажчик на змінну типу char *), далі - маркер кінця списку DBUS_TYPE_INVALID. Відзначимо, що функція dbus_message_append_args () - не єдиний засіб створення списку аргументів. Низькорівневий інтерфейс D-Bus надає в наше розпорядження і інші функції, здатні формувати списки аргументів динамічно, під час виконання програми.

На цьому робота нашої програми закінчена. За допомогою функцій dbus_message_unref () і dbus_connection_unref () ми повідомляємо системі, що створені нами об'єкти інтерфейсу D-Bus нам більше не потрібні, і виділену під них пам'ять можна звільнити.

Думаю, ви вже зрозуміли, що працювати з D-Bus за допомогою низкоуровневого API не дуже зручно. Не дивно, що програмісти створили численні прив'язки D-Bus API до різних мов програмування і бібліотекам. В даний час D-Bus підтримується в GTK + / GLib (слід зазначити, що це - найбільш опрацьовані прив'язки), Qt 3 / Qt 4, Python, Java, Perl. Сам я працюю над прив'язками D-Bus для wxWidgets.

Прив'язки D-Bus вирішують три завдання. По-перше, виконується інтеграція циклу обробки повідомлень D-Bus і цільової платформи. По-друге, об'єктна модель D-Bus API відображається в об'єктну модель, прийняту на цільовій платформі. По-третє, створюються методи для роботи з D-Bus проксі, як з «рідними» об'єктами. Але все це вже зовсім інша історія. LXF

Схожі статті