转载原地址:http://blog.csdn.net/yueliangniao1/article/details/7188549
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);
- };
- }; //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
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();//获得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
3.3 MyClient客户端代码实现
(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
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