今日の内容
● OpenBinderのドキュメントを読んでみたら非常に興味深かったので内容のご紹介。
● 元ネタは OpenBinderのアーカイブ(http://www.angryredplanet.com/~hackbod/openbinder/)
と
Introduction to OpenBinder and Interview with Dianne Hackborn(http://www.osnews.com/story/13674/Introduction_to_OpenBinder_and_Interview_with_Dianne_Hackborn)
OpenBinder って ?
●元々は Next Generation BeOSに採用される予定だった。●UNIXの CORBA 、Windowsの COMのように分散コンポーネント環境を提供するフレームワーク。
以上第 3回の勉強会資料から。 実はここに全部答えがありました。
OpenBinder って ?● The Binder could be described as a "framework
framework". It doesn't do anything itself, but is an enabling tool for implementing other rich frameworks, such as the view hierarchy, media framework, etc.
(OpenBinder Binder Kitの説明から )
OpenBinder って ?
● OpenBinder was really designed as an operating system component framework.
( インタビューから )
● つまり、 OpenBinderは OS上に ViewフレームワークやMediaフレームワークなどを構築するためのコンポーネントフレームワークであり、
“ ”フレームワークのためのフレームワーク 。
分散コンポーネント環境
● 分散コンポーネント /分散オブジェクトとは● システムを機能分割し、適切に (ネットワーク上のマシンに )
配置
● 機能をコンポーネント化して再利用性を高める
● 標準化された呼び出し規約を使用して、離れた位置に配置された機能を簡単に利用可能にする。
● 代表的な技術に CORBA 、 JavaRMI/EJB 、 COM(COM+)等。
分散コンポーネント /オブジェクトの仕組み
● 以下、@IT 「スキルアップのための分散オブジェクト入門」から色々抜粋
● オブジェクトインターフェースを定義● リモートオブジェクトを呼び出すためのインターフェースを定
義する必要がある。
● CORBA 、 COMは IDL(Interface Definition Language)で定義。
● JavaRMIは Javaの Interfaceで定義。
スタブの役割
● スタブはリモートオブジェクトと同じメソッド、プロパティを持ち、プロキシとして動作する。
● ローカルクライアントはスタブにアクセスすることで、あたかもリモートオブジェクトに直接アクセスするかのように操作できる。
● 実際の呼び出しは、スタブと下の ORB(Object Request Broker)ランタイムがパラメータをマーシャリング (共通データ形式変換 )してリモートにメッセージ送信する。
分散システムの機能の特徴
● リモートオブジェクトを bind(登録 )
● bindされたリモートオブジェクトを lookup(検索 )
● lookupしたリモートオブジェクトを call(呼び出し )
する仕組みを持っている。
CORBAの場合
● 特定 OSや言語に依存しない共通プラットフォーム
● IDL(Interface Definition Language)で呼び出し先オブジェクトインターフェースを定義
● IIOP(Interner Inter-ORB Protocol)で COMやJavaRMI等とも通信可能
CORBAの場合
● IDLを作成し、 IDLコンパイラでコンパイルしてスタブとスケルトンを作成。
● スタブとスケルトンをそれぞれの言語で実装。
● オブジェクトの登録はいろいろなサービスが用意されている。 1例としてネーミングサービス。名前で登録して名前で検索できる。
JavaRMIの場合
● インターフェースを定義、これを実装するリモートオブジェクトクラスを作成する。
● リモートオブジェクトクラスから rmicコンパイラでスタブとスケルトンを生成する。
● リモートオブジェクトを RMIレジストリか JNDI (Java Naming and Directory Interface)に登録する。
COM/COM+の場合
● Windowsプラットフォーム上で特定言語に依存しない。
● スクリプト言語ではオートメーション (IDLコンパイラによる事前の静的処理でなく、実行時に動的にインターフェースを取得してリモートオブジェクトを呼び出す )サポート。
● 複数のインターフェースをサポートするコンポーネントを構築するための IUnknown インターフェース。
COM/COM+の特徴● オブジェクト登録・呼び出しにはレジストリを使用。
● 全インターフェースは IUnknown インターフェースを継承し、 AddRef 、 Release 、 QueryInterface関数を実装する。
● AddRef 、 Releaseはオブジェクトの参照カウントを増減させるために使用される。
● QueryInterfaceはコンポーネントが実装する他のインターフェースを取得するために使用される。
COM/COM+の特徴
● COM+オブジェクトは、自分を参照しているクライアントをカウントし、参照カウント 0になったら自らを削除する。
● サーバ側は pingを使ってクライアントの生存確認を行い、メッセージが戻らない場合は参照カウントを減らす。
参照カウントの例
class A { public B b;}
class B { public A a;}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
}
}
参照カウントの例
●Aを生成 Aの参照カウント 1
●Bを生成 Bの参照カウント 1
●Aから Bを参照 Bの参照カウント 2
●Bから Aを参照 Aの参照カウント 2
Test
Object A Object B
① ②
③
④
循環参照の例
class A { public B b;}
class B { public A a;}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
a = null;
b = null;
}
}
循環参照の例●Aを生成 Aの参照カウント 1
●Bを生成 Bの参照カウント 1
●Aから Bを参照 Bの参照カウント 2
●Bから Aを参照 Aの参照カウント 2
●Aへの参照を削除 Aの参照カウント 1
●Bへの参照を削除 Bの参照カウント 1
A 、 Bは到達不可能だが
参照カウントは 1のまま
Test
Object A Object B
①②
③
④
⑤ ⑥
Test
Object A Object B
①②
③
④
⑤ ⑥
弱い参照の例●Aを生成 Aの参照カウント 1
●Bを生成 Bの参照カウント 1
●Aから Bを参照 弱参照のため Bの参照カウントは増えない
●Bから Aを参照 弱参照のため Aの参照カウントは増えない
●Aへの参照を削除 Aの参照カウント 0
●Bへの参照を削除 Bの参照カウント 0
A 、 Bは参照カウント 0になり、
自分を削除する。
ようやく本題
● OpenBinderを分散オブジェクト技術として見ると。● C++で記述、プラットフォームには依存しないが、実装は最終的に Linux向け。
● IDLで呼び出し先オブジェクトインターフェースを定義。
● 複数のインターフェースをサポートするコンポーネントを構築するためのIInterfaceや IBinder インターフェース。
● リモートオブジェクトを参照カウントによって監視。
● ネットワークには非対応、 Binderカーネルドライバによる IPCをコンポーネント間に使用。
ソース構成
build ビルドの出力先
build_system makeベースの buildシステム
commands Linuxのコマンドラインツール
components Binderコンポーネント
docs ドキュメント
headers OpenBinderAPIヘッダファイル
interfaces 公開 API中の IDLファイル
libraries OpenBinderライブラリ
modules Binderカーネルモジュール
samples サンプルコード
scripts Linux/Binderシェル向けスクリプト
servers Binder実行環境向けデーモン
tools システム生成用 Linuxコマンドラインツール
Binderの特徴
● フォーカスする対象が Handheld(Be InternetAppliance, Palm)なので、ネットワーク間ではなく、プロセス間の分散システムとして設計
● 50MHz ARM7から 400MHz ARM9がターゲット
● コンポーネントモデルを取り入れることでシステム構成が柔軟に
● プロセス間で処理を分散することで Robust
Binderと COMの相違点
● COMは Cベースだが、 Binderは C++ベースなのでよりオブジェクト指向な実装となっていて、またスマートポインタのような高度な機能を使用できる
● COMではスクリプトをサポートするには IDispatchを実装する必要があるが、全ての Binderオブジェクトはスクリプト実行可能
● Binderはマルチスレッド対応としてデザインされていて、SLockerや SHandlerのようなクラスが用意されている。
BinderAPI規約から抜粋
● クラス名
● Iで始まるクラスは Binder インターフェース。 IBinderを除き IInterfaceを継承。
● Bは BBinderに直接 /間接的に由来する Binderクラス。大体は Concrete Class 。
● Sはその他のクラス。 SValueなどのデータ型が多いが、 SAtomや SHandlerのようなものもある。
BinderAPI規約から抜粋
● メモリ管理
● 通常 Stack-baseと参照カウントの 2種類のクラスを使う。
● 参照カウントされるクラスは SAtom(SLightAtom 、SLimAtom)由来。 I 、 Bで始まる全てのクラスは参照カウントされる。
● 参照カウントされるクラスは必ず newで生成され、sptr<> 、 wptr<>を用いる。
BinderAPI規約から抜粋
● メモリ管理
● Stack-Baseクラスは大体データ型クラス● newでは生成せず、スタック上や SVector<>等の
コンテナ上で生成。
● 値渡しで使用する。 Copy-On-Wright Semanticsが使用される。
● SSharedBufferは以上の全ての特徴を持つ。
SupportKit
● OpenBinderは SupportKit 、 BinderKit 、 StorageKit等から成る。
● SupportKitは便利なユーティリティや通常処理のためのスイートで構成される。
● データ型、コンテナ、メモリ管理、スレッド処理、文字列処理等。
● SHandler 、 SMessageのようなイベントループの仕組みも。
BinderKit
● OpenBinderの本体。分散オブジェクトを使ったframeworkのための Framework 。
● ネットワークを使う COMや CORBAと違い、 Binder IPC Mechanismを使用したメッセージング。
● manifestファイルベースのコンポーネント登録
Binderサービス呼び出し
#include <services/Informant.h>
sptr<IBinder> informantBinder
= Context().LookupService(SString("informant"));
sptr<IInformant> informant
= interface_cast<IInformant>(informantBinder);
if (informant != NULL) {
informant->Inform( SValue::String("myMessage"),
SValue::String("myData") );
}
Binderオブジェクト作成#include <services/Informant.h>
class MyWatcher : public BnInformed, public SPackageSptr
{
public:
MyWatcher(const SContext& context)
: BnInformed(context)
{}
void OnInform( const SValue& information,
const SValue& cookie, const SValue& key)
{
bout << "Got informed: " << information << endl;
}
};
SPackageSptrは PackageManag-erのクラス。参照がある限りロードさ
れたままにする。
BnInformedは IInformant.idlからIDLコンパイラで生成されたクラス
Binderオブジェクトをサービスに#include <services/Informant.h>
sptr<IInformant> informant =
interface_cast<IInformant>(
Context().LookupService(SString("informant")));
sptr<IBinder> informed = new MyWatcher;
if (informant != NULL && informed != NULL)
{
informant->RegisterForCallback(
SValue::String("myMessage"), informed,
SValue::String("OnInform"));
}
Binderコンポーネント作成● コンポーネント化するには以下が必要。
● Manifestの作成● PackageManagerがインスタンス生成時に呼ぶ
Factory メソッドの追加● Manifest
<manifest>
<component>
<interface name="org.openbinder.services.IInformed" />
</component>
</manifest>
Binderコンポーネント作成● Factory メソッド
#include <support/InstantiateComponent.h>
sptr<IBinder>
InstantiateComponent( const SString& component,
const SContext& context,
const SValue &args)
{
if (component == "")
return static_cast<BnInformed*>(new MyWatcher(context));
return NULL;
}
コンポーネント Makefile
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
BASE_PATH:= $(LOCAL_PATH)
PACKAGE_NAMESPACE:= org.openbinder.samples
PACKAGE_LEAF:= MyWatcher
SRC_FILES:= \
MyWatcher.cpp
include $(BUILD_PACKAGE)
BinderShell
● Binderコンポーネントをコマンドライン操作できる Binder Shellが用意されている。
● C++を使わなくても Binderコンポーネントにアクセス可能。
● 詳細は割愛。
Binder用語解説
● Binder
● "The Binder”は Binderアーキテクチャ全般を指す。
● "a Binder”は BinderInterfaceの実装を指す。● Binder Object
● IBinderの実装エンティティ。大抵は BBinderを継承するクラスのこと。
Binder用語解説
● Component
● PackageManagerに公開された Binderオブジェクト。 Javaライクな NamingSchemeを使用。
● Package
● 1つ以上のコンポーネント実装を含む。● コンポーネント実装、 Manifestから成る。● COMと違い、コンポーネント情報は静的に扱われ
る。
Binder用語解説
● PackageManager
● 使用可能なコンポーネントを追跡管理する。
● コンポーネントを動的に生成し、管理する。
● /packages/components以下に配置されたコンポーネントを Binderの名前空間を使ってロード、インスタンス生成できるようにする。
Binder用語解説
● Interface
● Binderオブジェクトが実装するメソッド、プロパティ、イベントなどの定義、 IDLとして記述され、 Pidgen(IDLコンパイラ )で C++のヘッダと実装に変換される。
● Bn*クラスが Pidgenで生成されるので、 BBinderではなくこちらを継承してクラスを実装する。
Binder用語解説
● Context
● 各 Binderオブジェクトは SContextで表される "context”中に生成される。
● contextはオブジェクトがアクセスできるサービス、設定等の Globalな状態を保持している。
Binder IPC メカニズム
● カーネルモジュールを使用したプロセス間通信の仕組み。
● 標準 LinuxIPCの代わりに使われ、効率的に「スレッド移送」として IPC操作を行うことが出来る。
● ioctl() を使っての read-writeとして実装されている。
まとめ
● OpenBinder ドキュメントには他ではあまり見ない Binderの設計思想が書かれている。
● Binderは分散オブジェクトプラットフォームの事であり、 IPCはあくまでオブジェクト間のメッセージングに特化した部分に過ぎない。