1概述
Binder是基于OpenBinder,在Android系统上使用的进程间通信机制。
Binder基于Client-Server通信模式,本质上可以理解为它实现了Client对Server对象的远程调用。比如,有某个binder对象A位于Server中,该对象提供了一套函数用以实现对服务的请求,而在一个或多个Client中包含对象A的引用,Client通过该引用可以调用远端Server中对象A的接口函数,这种远端调用对Client而言,与调用本地对象并无区别。
2 通信模型
Binder机制定义了四个组件,分别是Client,Server,ServiceManager和binder驱动,其中Client,Server,ServiceManager运行于用户空间,binder驱动运行于内核空间。

binder驱动
binder驱动是内核中的一个字符设备驱动/dev/binder,它是整个Binder通信机制的核心。Client,Server,ServiceManager通过open()和ioctl()文件操作函数与binder驱动进行通信,从而实现了Client向Server发送请求,Server处理请求并返回结果到Client。具体来说,它负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。
ServiceManager
ServiceManager是一个守护进程,负责管理服务,即所有的Server需要向ServiceManager注册服务。同时,ServiceManager向Client提供查询和获取Server的接口。
3 binder通信实例
实现一个binder通信实例,需要经过以下步骤:
(1)获得ServiceManager的对象引用
(2)向ServiceManager注册新的Service
(3)在Client中通过ServiceManager获得Service对象引用
(3)在Client中发送请求,由Service返回结果。
下面看具体的代码如何实现。
3.1 libmyservice代码实现
(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);
-
- };
-
- };
(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");
-
-
-
- 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");
-
- }
-
-
-
- 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);
-
- }
-
- }
-
- };
(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
3.2 myserver代码实现
(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();
-
- LOGI("ServiceManager: %p", sm.get());
-
- MyService::instantiate();
-
- 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
3.3 MyClient客户端代码实现
(1)新建目录myservice/myclient,进入该目录
(2)编写myclient/myclient.h文件
- namespace android
-
- {
-
- class MyClient {
-
- public:
-
- void add100(int n);
-
- private:
-
- static const void getMyService();
-
- };
-
- };
(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;
-
- }
-
- }
-
- };
-
-
-
- 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
3.4在模拟器上运行
(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#
由客户端程序的执行结果可知,由服务端返回的执行结果是正确的。
4 参考文章:
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