Binder是基于OpenBinder,在Android系统上使用的进程间通信机制。
Binder基于Client-Server通信模式,本质上可以理解为它实现了Client对Server对象的远程调用。比如,有某个binder对象A位于Server中,该对象提供了一套函数用以实现对服务的请求,而在一个或多个Client中包含对象A的引用,Client通过该引用可以调用远端Server中对象A的接口函数,这种远端调用对Client而言,与调用本地对象并无区别。
Binder机制定义了四个组件,分别是Client,Server,ServiceManager和binder驱动,其中Client,Server,ServiceManager运行于用户空间,binder驱动运行于内核空间。
binder驱动是内核中的一个字符设备驱动/dev/binder,它是整个Binder通信机制的核心。Client,Server,ServiceManager通过open()和ioctl()文件操作函数与binder驱动进行通信,从而实现了Client向Server发送请求,Server处理请求并返回结果到Client。具体来说,它负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。
ServiceManager是一个守护进程,负责管理服务,即所有的Server需要向ServiceManager注册服务。同时,ServiceManager向Client提供查询和获取Server的接口。
(1)获得ServiceManager的对象引用
(2)向ServiceManager注册新的Service
(3)在Client中通过ServiceManager获得Service对象引用
(3)在Client中发送请求,由Service返回结果。
下面看具体的代码如何实现。
(1)新建目录frameworks/base/myservice/libservice,进入该目录
$ cd frameworks/base $ mkdir myservice $ cd myservice $ mkdir libmyservice $ cd libmyservice
(2)编写libmyservice/myservic.h文件
#include <utils/threads.h> #include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/BpBinder.h> #include <binder/Parcel.h> namespace android { class MyService : public BBinder { mutable Mutex mLock; int32_t mNextConnId; public: static int instantiate(); MyService(); virtual ~MyService(); virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); }; }; //namespace
(2)编写libservice/myservice.cpp文件
#include "myservice.h" #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> namespace android { static struct sigaction oldact; static pthread_key_t sigbuskey; int MyService::instantiate() { LOGE("MyService instantiate"); // defaultServiceManager ()获得ServiceManager的对象引用,addService()可向ServiceManager注册新的服务 int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService()); LOGE("MyService r = %d/n", r); return r; } MyService::MyService() { LOGV("MyService created"); mNextConnId = 1; pthread_key_create(&sigbuskey, NULL); } MyService::~MyService() { pthread_key_delete(sigbuskey); LOGV("MyService destroyed"); } // 每个系统服务都继承自BBinder类,都应重写BBinder的onTransact虚函数。当用户发送请求到达Service时,系统框架会调用Service的onTransact函数,该函数分析接收到的数据包,调用相应的接口函数处理请求 status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case 0: { pid_t pid = data.readInt32(); int num = data.readInt32(); num = num + 100; reply->writeInt32(num); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } }; //namespace
(3)编写libservice/Android.mk文件
# File: Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := myservice.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := libutils libbinder LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libmyservice include $(BUILD_SHARED_LIBRARY)
(4)编译libmyservice.so动态库
在android源码主目录下
$ source build/envsetup.sh including device/htc/passion/vendorsetup.sh including device/samsung/crespo4g/vendorsetup.sh including device/samsung/crespo/vendorsetup.sh $ mmm frameworks/base/myservice/libmyservice/
编译成功后生成文件:out/target/product/generic/system/lib/libmyservice.so
(1)新建目录myservice/myserver,并进入该目录
(2)编写myserver/myserver.cpp文件
#include <sys/types.h> #include <unistd.h> #include <grp.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include <utils/Log.h> #include <private/android_filesystem_config.h> #include "../libmyservice/myservice.h" using namespace android; int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager();//获得ServiceManager接口 LOGI("ServiceManager: %p", sm.get()); MyService::instantiate(); //执行addService()函数,注册服务 ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); //进入循环,等待客户端的请求 return 0; }
(3)编写myserver/Android.mk文件
# File: Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ myserver.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := \ libutils libbinder libmyservice LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := myserver include $(BUILD_EXECUTABLE)
(4)编译myserver可执行程序
在android源码主目录下执行:
$mmm frameworks/base/myservice/myserver/
编译成功后生成文件:out/target/product/generic/symbols/system/bin/myserver
(1)新建目录myservice/myclient,进入该目录
(2)编写myclient/myclient.h文件
namespace android { class MyClient { public: void add100(int n); private: static const void getMyService(); //通过ServiceManager获取服务接口 }; }; //namespace
(3)编写myclient/myclient.cpp文件
#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include "myclient.h" namespace android { sp<IBinder> binder; void MyClient::add100(int n) { getMyService(); Parcel data, reply; int answer; data.writeInt32(getpid()); data.writeInt32(n); LOGE("BpMyService::create remote()->transact()/n"); binder->transact(0, data, &reply); answer = reply.readInt32(); printf("answner=%d/n", answer); return; } const void MyClient::getMyService() { sp<IServiceManager> sm = defaultServiceManager(); binder = sm->getService(String16("android.myservice")); LOGE("MyClient::getMyService %p/n",sm.get()); if (binder == 0) { LOGW("MyService not published, waiting..."); return; } } }; //namespace using namespace android; int main(int argc, char** argv) { MyClient* p = new MyClient(); p->add100(1); return 0; }
(4)编写myclient/Android.mk文件
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ myclient.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := \ libutils libbinder libmyservice LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := myclient include $(BUILD_EXECUTABLE)
(5)编译myclient可执行程序
在android源码主目录下,执行:
$ mmm frameworks/base/myservice/myclient/
编译成功后生成可执行文件:out/target/product/generic/symbols/system/bin/myclient
(1)启动模拟器
$ cd ~/software/android/android-sdk-linux/tools $ ./emulator -avd gbread -partition-size 512
(2)拷贝libmyservice.so到模拟器的/system/lib目录
$cd out/target/product/generic/obj/lib $adb remount $ adb push libmyservice.so /system/lib 159 KB/s (10084 bytes in 0.061s)
(3)拷贝myserver到模拟器的/system/bin目录
$cd out/target/product/generic/symbols/system/bin $ adb push myserver /system/bin 668 KB/s (27508 bytes in 0.040s)
(4)拷贝myclient到/system/bin目录
$ adb push myclient /system/bin 1549 KB/s (46840 bytes in 0.029s)
(5)在模拟器上启动服务,并执行客户端程序。
# adb shell # cd system/bin # ls my* myclient myserver # ./myserver # ./myclient answner=101/n#
由客户端程序的执行结果可知,由服务端返回的执行结果是正确的。
http://blog.csdn.net/universus/article/details/6211589
http://blog.csdn.net/luoshengyang/article/details/6618363
http://blog.csdn.net/baiyanning/article/details/6191682
http://blog.csdn.net/baiyanning/article/details/6191682
http://blog.csdn.net/flydream0/article/details/7165308