Binderのはじめの一歩とAndroidのプロセス間通信(IPC)
横浜Androidプラットフォーム部
第3回勉強会
Android IPCのとりあえず1回目
2010/10/31
@l_b__
目次
Androidのプロセス間通信
※ただ、Androidソース内に名前付きパイプを使っている箇所は無い。
Binderって?
何故Binder
Android独自のIPC
Binderの歴史
Binderの仕組み
Kernel
Binder Driver(/dev/binder)
ServiceManager
libBinder
Receiver�Application
Sender�Application
Binderの仕組み
Binderの仕組み
実際に使ってみる
Binderを受信するNativeデーモン(Binder
Receiver)と、送信するNativeアプリ(BinderSender)を作ってみます。
実際に使ってみる 受信側
#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();
}
実際に使ってみる 受信側
#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_ */
実際に使ってみる 受信側
#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");
}
実際に使ってみる 受信側
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=%d\n",num);
reply->writeInt32(num*5);
break;
default:
//do nothing.
break;
}
return NO_ERROR;
}
実際に使ってみる 送信側
#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 %p\n",sm.get());
if (binder == NULL) {
LOGE("Receiver Service not found.\n");
return -1;
}
実際に使ってみる 送信側
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;
}
実際に使ってみる 受信側makefile
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)
実際に使ってみる 送信側makefile
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
sender.cpp
LOCAL_SHARED_LIBRARIES:= \
libcutils \
libbinder
LOCAL_MODULE:= BinderSender
include $(BUILD_EXECUTABLE)
実際に使ってみる ビルドスクリプト
#!/bin/bash
ANDROID_ROOT=~/android/myfroyo
source $ANDROID_ROOT/build/envsetup.sh
cd ~/android/myfroyo/external/binder_sample
mm
include $(all-subdir-makefiles)
実行結果のログ
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
Ashmemって?
Ashmemの関数
実際にAshmemを使ってみる
次回予告