D-Bus 調査その 1
はじめに
D-Bus について調査する機会があったので、調べた内容を残しておく目的でエントリーを作成する。
参考文献
このエントリーは以下のページを参考にしており、内容は筆者が以下のページを読んで理解したことの簡単なまとめである。D-Bus に関する日本語の情報は少ないように見られるため、自分の忘備録以上に、誰かの理解の助けや更なる調査の足がかりになれば幸いである。
D-Bus とは
D-Bus とは、Inter-Process Communication (IPC) および Remote Procedure Calling (RPC) のためのメカニズムで、同一マシン上の複数のプロセス間の通信のために、効率性と使いやすさを追求して設計されている。 D-Bus には、以下の二つの主要なユースケースがある。
- system bus : システムアプリケーションとユーザセッションの間の通信に使われる
- session bus : ユーザのログインセッションにおいて同一デスクトップ環境内のアプリケーションの連携に使われる
D-Bus に接続されたアプリケーションに対して、RPC および publish/subscribe メカニズムがサポートされたシンプルなオブジェクトモデルでコミュニケーションが行われる。
アプリケーション内のオブジェクトは、インターフェースとして API が公開されている。D-Bus のインターフェースは、そのインターフェースがサポートするメソッドやシグナル、引数の型、引数の数などの包括的なリストであり、 インターフェースを用いてオブジェクトの問い合わせやメソッドの呼び出し、シグナルの発行を要求することができる。
また、動的な実行環境をサポートするために、実行時にオブジェクトの問い合わせを行うための Introspection という機能が用意されている。動的なプログラミング言語のバインディングでは、使用するインターフェースを明示的に書くことを避けるためにこの機能を用いることが多い。
D-Bus のオブジェクトは、bus name と object path の一意な組み合わせとして表現される。bus name は、D-Bus に接続しているアプリケーションを一意に特定し、object path はアプリケーション内のオブジェクトを一意に特定する。それぞれのアプリケーションは、コネクションごとにランダムな unique bus name を自動的にアサインされる。また、オブジェクトを良く知られた場所で公開するために、"well known bus name" の割り当てを要求することもできる。"well known" bus name の例として、Gnome NetworkManager は "org.freedesktop.NetworkManager" を使う。
主要な構成要素
bus name
前述のように、bus name には unique bus name と well known bus name がある。unique bus name は、クライアントのコネクションごとに割り当てられる : (コロン) からはじまる名前で、バスのライフタイムの中で一意であることが保証されている。
また、well known bus name は、システム内の良く知られたパスでオブジェクトを公開するために用いられる。well known bus name は unique bus name と違い、一意に特定できないため、ownership という概念がある。アプリケーションが誰も ownership を持っていない bus name を要求した場合は、直ちに ownership が与えられるが、誰かが ownership を持つ bus name を要求した場合、二つのオプションがある。一つは ownership を steal すること、もう一つは queue に入って ownership が与えられるのを待つことだ。
ownership を steal する場合、次の二つの条件が満たされる必要がある。(1) 現在 ownership を持つアプリケーションが、D-Bus に対して名前の放棄を表明し、かつ (2)
新たに ownership を要求しているアプリケーションが、bus name を steal することを可能にするフラグを設定していること。
steal および queue の詳細は、DBus Overview の Bus Services の インターフェース定義を参照すると分かりやすい。
object path
object path は、アプリケーション内の D-Bus オブジェクトを一意に特定するために用いられる。UNIX のファイルシステムのパスに似たような形で表現される。
インターフェース
インターフェースは、それぞれの D-Bus オブジェクトがサポートしているメソッド またはシグナルなどの定義である。オブジェクトのインターフェースかメソッドやシグナルを呼び出し、呼び出されることでプロセス間通信が実現されるが、インターフェースを明示的に指定して呼び出す他に、前述の Introspection 機能で動的に呼び出すことも可能である。
インターフェース名は、DNS のドメイン名を逆にした形で命名される。例えば、上記 Introspection は D-Bus の定義する標準インターフェースで、名前は "org.freedesktop.DBus.Introspectable" となる。
メソッドやシグナルは、それぞれが受け入れる引数の数と型を明示的に定義しており、この定義は他のプログラミング言語などと同じように Signature String と呼ばれている。
メソッド
メソッドは基本的に、呼び出し元に何らかの戻り値を返す。呼び出しに戻り値が不要であることが明示されている場合でも、"method return" メッセージが返される。これによりメソッドを呼び出したアプリケーションは、有用な結果が帰ってこなかった場合でもメソッドの呼び出しは正常に終了したことを知ることができる。
ただし、メソッドコールの中で "no reply expected" フラグがセットされていた場合は、呼び出し元に何の応答も返されない。これは D-Bus のオプショナル機能で、API がサポートする必要がある。
シグナル
シグナルは 1 対多の形式で、単一の送信元から多数の受信先にメッセージを送る。メソッドと異なる点は、シグナルは完全に非同期的なコミュニケーションで、いつでも送信元からシグナルが送信されうる。
シグナルは publish/subscribe 方式のメッセージングモデルで、デフォルトの状態ではどのクライアントにも送信されないため、受信したいシグナルを明示的に register するという作業が必要になる。
Signature String
D-Bus では、インターフェースの Signature String の引数の定義に "string-based type encoding" というエンコーディング方式を採用している。例えば文字 'a' は配列を、文字 'i' は 32 ビット整数を表し、'ai' とすることで 32 ビット整数の配列を表現できる。詳細は DBus Overview の Signature Strings にて確認できる。
メッセージのルーティング
メッセージのルーティングの方法には、destination address を使う方法と、match rules を使う方法がある。
destination address を用いたルーティングは、メッセージ中の宛先パラメータの中に、unique bus name または well known bus name が含まれる時に実施される。この方式は、典型的に メソッドコールなどで呼び出しや戻り値をやりとりするような 1 対 1 のコミュニケーションで用いられる。
一方でシグナルは 1 対多のコミュニケーションで、特定の宛先を持っていないので、このような場合に match rules を使ったルーティングが用いられる。match rules は "org.freedesktop.DBus.AddMatch" Method を用いて設定される、コンマ区切りの key-value ペアの文字列である。
今後調査してまとめたいこと
- プロセスやファイル、実行時のコンポーネントなど
- 具体的な使用例