Location via proxy:
[ UP ]
[Report a bug]
[Manage cookies]
No cookies
No scripts
No ads
No referrer
Show this form
Submit Search
Binderのはじめの一歩
•
2 likes
•
1,497 views
L
l_b__
Follow
1 of 21
Download now
More Related Content
Binderのはじめの一歩
1.
Binderのはじめの一歩 Android IPCのとりあえず1回目 2010/09/19 @l_b__ 横浜Androidプラットフォーム部 第2回勉強会でやらなかった
2.
目次 ●Binderって? ●何故Binder? ●Android独自のIPC ●Binderの歴史 ●Binderの仕組み ●実際に使ってみる ●次回予告
3.
Binderって? ●Android独自のプロセス間通信の一つ。 ●POSIXメッセージの置き換え。 ●プロセス間で小さいデータ(数百〜数千byte程度)を 高速にやり取りするために使用。 ●何故POSIXのIPCがあるのにBinderという機構が導 入されたのか。
4.
何故Binder ●AndroidはSystemV(UNIXの1種)のIPCをサポート していない! ●NDKの/docs/system/libc/SYSV-IPC.TXTにサ ポートされない理由の記述あり。 ○カーネルでのリソースリークが発生する ○カーネルリソースを枯渇させるサンプルコードも有 り。(もちろんAndroidでは動かないのでLinuxで動 作させる必要あります。)
5.
Android独自のIPC ●System V IPCの代わりは以下の通りと思われる。 ○メッセージキューはBinderに。 ○共有メモリはAnonymous
Shared Memory (ashmem)に。 ○セマフォはPOSIX IPCのセマフォに。
6.
Binderの歴史 ● 元々はNext Generation
BeOSに採用される予定だった OpenBinder。(http://www.angryredplanet. com/~hackbod/openbinder/) ● UNIXのCORBA、WindowsのCOMのように分散コンポーネント 環境を提供するフレームワーク。 ● BeOSポシャっちゃったので残念ながら動くものとしては採用され ず。 ● OpenBinderをメンテしていたHackbornさんは今はAndroidのプ ラットフォームエンジニア。よくGroupに投稿しています。 ● 余談ですがBeの創業者Gasseeも、Danger、Androidの創業者 Andy Rubinも元Apple。Appleすごいですね。
7.
Binderの仕組み Kernel Binder Driver (/dev/binder) ServiceManager libBinder Receiver Application Sender Application
8.
Binderの仕組み ● Binder Driver(/dev/binder)にアクセスしているのはフレーム ワーク中、ServiceManager(ソースの /framework/base/cmds/servicemanager/service_manage r.c)とlibBinder (/framework/base/libs/binder/ProcessState.cpp)のみ。 ○この中の仕組みはまだ追えていません。 ●
ユーザーアプリケーションは直接Binderドライバを操作することは ない。
9.
Binderの仕組み ● Binderを受信するアプリはServiceManagerに自身をサービスと して登録する。(図の水色矢印) ● 受信するアプリはBBinderを継承し、onTransact()で受信処理を 実装。 ●
Binderを送信するアプリはServiceManagerから送信先サービス を取得し(図の緑矢印)、取得したIBinderサービスに対し transact()でメッセージを送信(図の赤矢印)。
10.
実際に使ってみる Binderを受信するNativeデーモン(Binder Receiver)と、送信するNativeアプリ(BinderSender)を作ってみま す。
11.
実際に使ってみる 受信側 ● main.cpp 受信側起動処理 SurfaceFlingerやAudioFlingerな どが参考になります。 #define
LOG_TAG "RECEIVER" #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include <utils/Log.h> #include "receiver.h" int main(int argc, char** argv) { LOGD("Reciever start."); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); LOGD("ServiceManager: %p", sm.get()); Receiver::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
12.
実際に使ってみる 受信側 ● receiver.h BBinderを継承した受信処理クラスの定義 #ifndef RECEIVER_H_ #define
RECEIVER_H_ #include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/Parcel.h> using namespace android; class Receiver:public BBinder { public: static void instantiate(); Receiver(); virtual ~Receiver(); virtual status_t onTransact( uint32_t, const Parcel&, Parcel*, uint32_t); }; #endif /* RECEIVER_H_ */
13.
実際に使ってみる 受信側 ● receiver.cpp Receiverクラスの実装。受けた数値を5倍して返 す。 #define LOG_TAG
"RECEIVER" #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include <utils/Log.h> #include "receiver.h" using namespace android; void Receiver::instantiate() { defaultServiceManager()->addService( String16("Receiver"), new Receiver()); } Receiver::Receiver() { LOGD("Receiver created.n"); } Receiver::~Receiver() { LOGD("Receiver destroyed.n"); }
14.
実際に使ってみる 受信側 ● receiver.cpp 続き BBinder::onTransactの実装部分 status_t
Receiver::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { LOGD("Message received code=%d.n", code); pid_t pid; int num; switch(code) { case 0: pid = data.readInt32(); LOGD("Sender pid=%d", pid); num = data.readInt32(); LOGD("Number Data=%dn",num); reply->writeInt32(num*5); break; default: //do nothing. break; } return NO_ERROR; }
15.
実際に使ってみる 送信側 ● receiver.cpp 送信処理。自プロセスIDと数値の12を送信する。 #define
LOG_TAG "SENDER" #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include <binder/IInterface.h> #include <binder/Parcel.h> #include <utils/RefBase.h> #include <utils/Log.h> using namespace android; int main() { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("Receiver")); LOGD("Sender getService %pn",sm.get()); if (binder == NULL) { LOGE("Receiver Service not found.n"); return -1; }
16.
実際に使ってみる 送信側 ● receiver.cpp 続き。実際の送信処理部分。 Parcel
data, reply; pid_t pid = getpid(); LOGD("pid=%d", pid); data.writeInt32(pid); int num = 12; LOGD("num=%d", num); data.writeInt32(num); //非同期メッセージはFLAG_ONEWAYを4番目に追加 binder->transact(0, data, &reply); LOGD("reply num=%d", reply.readInt32()); return NO_ERROR; }
17.
実際に使ってみる 受信側makefile ● receiver/Android.mk LOCAL_PATH:= $(call
my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= receiver.cpp main.cpp LOCAL_SHARED_LIBRARIES:= libcutils libbinder LOCAL_MODULE:= BinderReceiver include $(BUILD_EXECUTABLE)
18.
実際に使ってみる 送信側makefile ● sender/Android.mk LOCAL_PATH:= $(call
my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= sender.cpp LOCAL_SHARED_LIBRARIES:= libcutils libbinder LOCAL_MODULE:= BinderSender include $(BUILD_EXECUTABLE)
19.
実際に使ってみる ビルドスクリプト ● build/build.sh #!/bin/bash ANDROID_ROOT=~/android/myfroyo source $ANDROID_ROOT/build/envsetup.sh cd
~/android/myfroyo/external/binder_sample mm ● 全体のAndroid.mk include $(all-subdir-makefiles)
20.
実行結果のログ D/RECEIVER( 286): Reciever
start. D/RECEIVER( 286): ServiceManager: 0xb678 D/RECEIVER( 286): Receiver created. D/SENDER ( 288): Sender getService 0xa678 D/SENDER ( 288): pid=288 D/SENDER ( 288): num=12 D/RECEIVER( 286): Message received code=0. D/RECEIVER( 286): Sender pid=288 D/RECEIVER( 286): Number Data=12 D/SENDER ( 288): reply num=60
21.
次回予告 Binder、ashmem、MemoryMappedFileなど各種IPCの使い方と、 使った時の性能測定を考えています。(多分)
Download