MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの基礎 - D-Busのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの基礎 - D-Bus
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == D-Busは、オープンソースのプロセス間通信(IPC:Inter Process Communication)機構であり、freedesktop.orgプロジェクトの一部である。<br> IPCとは、1台のコンピュータ上で動作する複数のプログラムの間で情報を交換するシステムのことである。<br> <br> IPCには、パイプ、名前付きパイプ、シグナル、共有メモリ、Unixソケット、ループバックソケット等がある。<br> D-Busもリンク層はUnixソケットで動作しているが、手順とフォーマット(プレゼンテーション層)が既定されていることが、「生の」Unixソケットとは異なる。<br> <br> 開発当初はGNOME等のGUIの制御を目的としていが、今日では、GUIに限らず幅広いソフトウェアで使用されており、<br> デスクトップの通知、メディアプレーヤー制御、XDGポータル等、多くのfreedesktop.org標準がD-Busをベースに構築されている。<br> <br> IPCとは、あるプロセスから別のプロセスへ情報を取得する方法を説明するために使用することができる。<br> これは、データの交換、メソッドの呼び出し、イベントのリスニング等がある。<br> <br> * デスクトップにおけるIPCの使用例 ** スクリプト(ユーザが共通の環境でスクリプトを実行して、実行中の様々なソフトウェアと対話または制御する)<br> ** 集中型サービスへのアクセスの提供 ** 協調型ソフトウェアの複数のインスタンス間の調整 <br> * D-Busの使用例 ** freedesktop.orgのnotification仕様 **: これは、ソフトウェアは通知を中央サーバ(Plasma等)に送信して、中央サーバは通知を表示して、通知が閉じられたりアクションが実行されたりといったイベントを送り返すものである。 <br> * IPCの他の使用例 ** ユニークなソフトウェアのサポート **: これは、ソフトウェアの起動時に、まず、同じソフトウェアの他の実行中のインスタンスを確認して、 **: もし存在すれば、IPCを介して実行中のインスタンスにメッセージを送信して、自分自身を表示して終了させる。 <br> D-Busは、言語やツールキットに囚われないため、あらゆるプロバイダのソフトウェアやサービスが相互作用することができる。<br> <br> Qtは、D-Busと対話するためのクラスとツールのセットを提供しており、ここでは、D-Busのハイレベルなコンセプト、および、QtやKDEソフトウェアでの実装を記載する。<br> <br><br> == D-Busの基礎 == D-Busは、<u>メッセージ</u>を<u>オブジェクト</u>に届ける仕組みである。<br> メッセージはデータであり、オブジェクトはデータの受け手であるプログラムのことである。<br> <br> D-Busのメッセージには、手続き呼び出し(METHOD_CALL)、手続きの戻り値(METHOD_RETURN)、エラー(ERROR)、シグナル(SIGNAL)の4種類がある。<br> <br> 手続き呼び出し(METHOD_CALL)と手続きの戻り値(METHOD_RETURN)はペアで使用されており、<br> <u>他のプロセスが提供するサービス機能を関数の呼び出しのように使用することができる</u>という一種のRPC(Remote Procedure Call)のようなものとして扱うことができる。<br> <br> ただし、D-Busは同一PC上のIPCに特化しており、RPCのようなネットワークを介した異なるPC間の通信は原則としてサポートしていない。<br> <br> シグナル(SIGNAL)は、片方向の一斉通知として使用することができ、ネットワークが落ちた時、USBデバイスの検出、再起動の要請等の通知メカニズムとして多用されている。<br> <br> オブジェクトは、<u>サービス</u>に内包された<u>操作対象を指す名前</u>である。<br> <br><br> == バス == D-Busは、ソフトウェアが相互に通信するため、複数のメッセージバスを提供する。<br> <br> 各バスには独自の接続機能があり、異なるカテゴリーのメッセージを分離することができる。<br> <br> あるバスで送信されたメッセージは他のバスからアクセスできないが、同じバスに接続されたソフトウェアは全て互いに通信することができる。<br> 任意のバスに複数のソフトウェアを同時に接続することができ、また、1つのソフトウェアが複数のバスに同時に接続することも可能である。 これにより、バスごとに異なるセキュリティポリシーを適用できると共に、グローバルメッセージとローカルメッセージの両方を効率的に共有することができる。<br> <br> D-Busは、2つの定義済みバス(<u>システムバス</u>と<u>セッションバス</u>)を予め用意されており、一般的なD-Busの使用方法をほぼカバーすることができる。<br> * システムバス *: ハードウェア管理等のシステムグローバルサービスに使用される。 *: これはユーザー間で共有され、通常、厳格なセキュリティ・ポリシーが付属しています。 *: <br> * セッションバス *: 各デスクトップセッション(ログインしているユーザ等)には、セッションバスが存在する。 *: これは、GUIソフトウェア等が最も頻繁に使用する傾向がある。 <br> さらに、ソフトウェアは、必要に応じて複数の独自のバスを作成することができる。<br> <br><br> == メッセージ == メッセージは、バスにおける通信の基本単位である。<br> <br> TCP/IPのパケットと同様に、バスでやり取りされる情報は、全てメッセージで行われる。<br> しかし、ネットワークのパケットとは異なり、D-Busの各メッセージには、送受信されるデータ1式が含まれていることが保証されている。<br> <br> メッセージには、送信されるデータだけでなく、送信者と受信者が誰であるかも記録されており、適切なルーティングを可能にする。<br> メッセージは、メソッドコール、シグナルエミッション、メソッドの戻り値であり、エラー情報も含むことがある。<br> <br><br> == 名前空間とアドレス == 複数のソフトウェアが同一のバス上に存在し、1つのソフトウェアが複数のオブジェクトを提供してメッセージを送信することができるため、<br> 特定の住宅やオフィスを一意に識別するのと同様に、任意のバス上の任意のオブジェクトを効果的かつ一意にアドレス指定する手段を持つことが必要である。<br> <br> インターフェース、サービス、オブジェクト名の3つの情報を組み合わせることにより、バス上の任意のオブジェクトに一意のアドレスを作成することができる。<br> <br> ==== インターフェイス ==== インターフェイスは、バス上に公表される呼び出し可能なメソッドとシグナルのセットである。<br> <br> インターフェースは、メッセージを渡すソフトウェアの間で、インターフェースの名前、パラメータ(もしあれば)、戻り値(もしあれば)を定義する"契約"を提供する。<br> <br> これらのメソッドは、インターフェイスを使用しているソフトウェアのメソッドやAPIに1対1で直接マッピングされることもある。(直接マッピングされないこともある)<br> これにより、複数のソフトウェアが、内部の実装に関係なく、類似または同一のインターフェイスを提供することができ、<br> 一方で、ソフトウェアは、ソフトウェアの内部設計を気にすることなく、これらのインターフェイスを使用できるようになる。<br> <br> インターフェイスは、文書化やコードの再利用を目的として、XMLで記述する。<br> ユーザや開発者は、インターフェースのXML記述を参照できるだけでなく、開発者はXMLから自動生成されたクラスを使用することができる。<br> このため、D-Busの使用は非常に簡単で、エラーが発生しにくくなる。(例. コンパイラがコンパイル時にメッセージの構文を確認することができる)<br> <br> ==== サービス ==== サービスとは、ソフトウェアとバスの接続を表すものである。<br> <br> ここでいうサービスとは、D-Busの用語でいうバス名に相当するものである。<br> (<u>バス名という用語は、バス上の接続名であり、バスの名前ではない。</u>そのため、Qtのドキュメントで記載されているように、サービスという用語を使用する)<br> <br> これらは、複数のコンポーネントの名前空間を必要とする他の多くのシステムで見られるように、"逆ドメイン名"アプローチを使用することにより、一意に保たれる。<br> KDEプロジェクトのソフトウェアが提供する多くのサービスでは、サービス名にorg.kdeというプレフィックスを使用している。<br> そのため、セッションバスにおいて、org.kde.screensaverが宣伝されているのを見掛けるかもしれない。<br> <br> サービス名には、開発者の組織やソフトウェアのドメイン名を使用することを推奨する。<br> 例えば、開発者のドメインがawesomeapps.org、ソフトウェアの名前がwickedwidgetの場合、バス上のサービス名はorg.awesomeapps.wickedwidgetとなる。<br> <br> ソフトウェアが複数のバスに接続している場合、または、同一のソフトウェアの複数のインスタンスが同時にアクティブになっている場合は、接続ごとに一意なサービス名を使用する必要がある。<br> 多くの場合、プロセスIDをサービス名に付加することでこれを実現する。<br> <br> ==== オブジェクト ==== ソフトウェアは、バス上の複数のオブジェクトへのアクセスを宣伝する可能性が高い。<br> <br> オブジェクトとサービスの間のこの多対1の関係は、アドレスにパスコンポーネントを提供することで対応される。<br> <br> サービスに関連付けられた各パスは、異なる一意のオブジェクトを表す。(例. /MainInterface、/Documents/Doc1)<br> 実際のパス構造は完全に任意であり、どのようなパスにするかは、サービスを提供するソフトウェア次第である。<br> これらのパスは、他のソフトウェアにメッセージを送信するソフトウェアのために、オブジェクトを識別し、論理的にグループ化する方法を提供する。<br> <br> 一部のライブラリは、オブジェクトを適切に名前空間化するために、オブジェクトパスの先頭に"リバースドメイン"を付けてエクスポートする。<br> これは、任意のサービスに参加するライブラリやプラグインではよくあることで、そのため、ソフトウェアや他のコンポーネントによりエクスポートされたオブジェクトとの全ての衝突を避けなければならない。<br> しかし、KDEソフトウェアやライブラリでは、この方法は使用されていない。<br> <br> オブジェクトはインターフェースへのアクセスを提供しており、オブジェクトは同時に複数のインタフェースへのアクセスを提供することができる。<br> <br> ==== アドレスの例 ==== D-Busメッセージには、上記で記載したコンポーネントで構成されるアドレスが含まれており、正しいソフトウェア、オブジェクト、メソッドコールにルーティングされる。<br> # 例. KRunnerのアドレス org.kde.krunner /App org.kde.krunner.App.display org.kde.krunner : サービス /App : オブジェクトへのパス org.kde.krunner.App : オブジェクトがエクスポートするインターフェース display : インターフェース内のメソッド <br> もし、/Appオブジェクトがorg.kde.krunner.Appインターフェースを提供するのみの場合(または、実装するサービスの中で表示メソッドが一意の場合)、これはアドレスとして同様に機能する。<br> org.kde.krunner /App display <br> このようにして、可能性のあるそれぞれの宛先を一意かつ確実にアドレスで指定することができる。<br> <br><br> == メソッドとシグナル == バス上の任意のエンドポイントをアドレス指定する方法を使用して、メッセージを送受信する場合の可能性を検討する。<br> <br> ==== メソッド ==== 受信側のソフトウェアにおいて、メソッド(関数)を実行するために送信されるメッセージのことである。<br> <br> メソッドの呼び出しに失敗した場合(アドレスの間違い、または、要求されたソフトウェアが動作していない等の理由でメソッドが利用できない場合)、呼び出し側のソフトウェアにエラーが返る。<br> <br> メソッドの呼び出しに成功した場合、呼び出し元のソフトウェアにオプションの戻り値が返る。(戻り値が提供されない場合でも、成功メッセージが返る)<br> このラウンドトリップにはオーバーヘッドがあり、パフォーマンスが重要なコードではこれを念頭に置くことが重要である。<br> <br> メソッド呼び出しは、常に呼び出し元のソフトウェアによって開始されて、結果として生じるメッセージは正確に1つの送信元アドレスと1つの送信先アドレスを持つ。<br> <br> ==== シグナル ==== シグナルはメソッドコールに似ているが、"逆方向"に発生すること、単一の宛先に縛られないことが特徴である。<br> <br> シグナルは、インターフェイスをエクスポートしているソフトウェアから発信されて、同一バス上のどのソフトウェアでも利用できる。<br> これにより、ソフトウェアは、状態の変化やその他のイベントを、それらの変化を追跡するソフトウェアに自発的に知らせることができる。<br> <br> これは、Qtのシグナルとスロットの仕組みに似ており、これは、同じ機能のシステム版である。<br> <br><br> == D-Busコマンド == 以下の例では、Linuxでのシャットダウン、再起動、ログアウト等のD-Busサービスの一覧を取得している。<br> dbus-send --system --print-reply=literal \ --dest=org.freedesktop.login1 \ /org/freedesktop/login1 \ --type=method_call \ org.freedesktop.DBus.Introspectable.Introspect <br> 以下の例では、D-Busサービスを使用してシャットダウンおよび再起動を実行している。<br> # シャットダウン dbus-send --system --print-reply=literal \ --dest=org.freedesktop.login1 \ # バス名(D-Busサービス名) /org/freedesktop/login1 \ # オブジェクトパス(D-Busサービスに送信するメッセージに含まれるそのD-Busサービス内におけるメッセージの宛先) "org.freedesktop.login1.Manager.PowerOff" boolean:true # D-Busインターフェースの関数名 # 再起動 dbus-send --system --print-reply=literal \ --dest=org.freedesktop.login1 \ # バス名(D-Busサービス名) /org/freedesktop/login1 \ # オブジェクトパス(D-Busサービスに送信するメッセージに含まれるそのD-Busサービス内におけるメッセージの宛先) "org.freedesktop.login1.Manager.Reboot" boolean:true # D-Busインターフェースの関数名 <br><br> == 便利なツール == D-Busのバスの検索やD-Busを使用したソフトウェアの開発には、いくつかのエンドユーザ向けの便利なツールが存在する。<br> <br> ==== qdbus ==== <code>qdbus</code>コマンドは、コマンドラインツールであり、与えられたバス上のサービス、オブジェクト、インタフェースを表示したり、バス上の与えられたアドレスにメッセージを送信するために使用できる。<br> これは、セッションバスおよびシステムバスの両方を検索するために使用することができる。 <br> <br> <code>--system</code>オプションを付加する場合は、qdbusはシステムバスに接続する。<br> <code>--system</code>オプションを付加しない場合は、セッションバスを使用する。<br> <br> <code>qdbus</code>コマンドは、与えられた引数を、与えられたオブジェクトに渡すためのアドレス、および、パラメータ(存在する場合)として使用する。<br> もし、完全なアドレスが与えられなかった場合、バス上のその地点から利用可能な全てのオブジェクトを表示する。<br> <br> 例えば、アドレスが提供されない場合は、利用可能なサービスのリストが表示される。<br> サービス名を指定する場合、オブジェクトのパスが提供される。<br> パスを指定する場合、全てのインターフェースの全てのメソッドが表示される。<br> <br> このように、非常に簡単にバス上のオブジェクトを検索して操作することができる。<br> <br> ==== qdbusviewer ==== <code>qdbusviewer</code>は、Qtで作成されたGUIソフトウェアであり、<code>qdbus</code>コマンドがCUIから提供する機能と基本的に同一のものをGUIとして提供している。<br> <code>qdbusviewer</code>は、Qt本体と同梱されており、オブジェクトアドレス等のD-Busの基本概念に慣れていれば、誰でも簡単に使用できる。<br> <br><br> == Qtプロジェクト == Qtプロジェクトにおいて、Qt Creator付属の<code>qdbusxml2cpp</code>コマンドを実行することにより、D-Busインターフェースのアダプタクラスを生成する。<br> 生成されるファイルは、D-Busインタフェースファイル(XML形式)に対するアダプタを実装したC++のソースコードファイルとヘッダファイルである。<br> # mocファイルはインクルードしない場合 qdbusxml2cpp -a <生成するcppファイル名とヘッダファイル名> -c <自動生成するヘルパークラス名 (親クラス)> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス> 例. qdbusxml2cpp -a SamplesAdaptor -c SamplesAdaptor -i SampleHelper.h -l SampleHelper org.qt.policykit.examples.xml # mocファイルもインクルードする場合 qdbusxml2cpp -m -a <生成するcppファイル名とヘッダファイル名> -c <自動生成するヘルパークラス名 (親クラス)> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス> 例. qdbusxml2cpp -m -a SamplesAdaptor -c SamplesAdaptor -i SampleHelper.h -l SampleHelper org.qt.policykit.examples.xml <br> 生成されたファイルをQtプロジェクトに指定およびインクルードする。<br> <br> または、Qtプロジェクトファイルにおいて、<code>qdbusxml2cpp</code>コマンドを自動実行する設定を記述してもよい。<br> system(qdbusxml2cpp -a <生成するcppファイル名とヘッダファイル名> -c <自動生成するヘルパークラス名 (親クラス)> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス>) <br><br> == CMakeプロジェクト == CMakeプロジェクトにおいて、<code>qt_add_dbus_adaptor</code>オプションを指定することにより、D-Busインターフェースのアダプタクラスを生成する。<br> <code>qt_add_dbus_adaptor</code>コマンドは、Qt D-Bus XMLコンパイラ(qdbusxml2cpp)のアダプタモードでの呼び出しを設定する。<br> <br> 第2引数で指定したD-Busインタフェースファイル(XML形式)に対するアダプタを実装したC++のソースコードファイルとヘッダファイルを生成する。<br> 生成されたファイルのパスが第1引数に追加される。<br> <br> 第3引数には、D-Busインターフェースに基づく親クラスのヘッダファイル名を指定する。<br> 生成されるアダプタを実装したソースコードには、<code>#include "<第3引数で指定したヘッダファイル名>"</code>としてインクルードされる。<br> <br> 第4引数には、第3引数のクラス名(D-Busインターフェースに基づく親クラス名)を指定する。(省略可能)<br> 第5引数には、生成するヘッダファイル名(拡張子.hは不要)を指定する。(省略可能)<br> 第6引数には、生成するアダプタのクラス名を指定する。(省略可能)<br> <br> 第4引数から第6引数までを省略する場合、親クラス名、ヘッダファイル名、クラス名は、第3引数の指定値から自動的に生成される。<br> <syntaxhighlight lang="cmake"> qt_add_dbus_adaptor( <任意の変数名> <D-Busインタフェースファイル(XML形式)> <親クラスのヘッダファイル名> [第3引数のクラス名 (省略可能)] [生成するヘッダファイル名(拡張子.hは不要) (省略可能)] [生成するアダプタのクラス名 (省略可能)] ) </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの基礎 - D-Bus
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse