如何在android下使用binder

转载原地址:http://blog.csdn.net/yueliangniao1/article/details/7188549

1概述


Binder是基于OpenBinder,在Android系统上使用的进程间通信机制。

Binder基于Client-Server通信模式,本质上可以理解为它实现了ClientServer对象的远程调用。比如,有某个binder对象A位于Server中,该对象提供了一套函数用以实现对服务的请求,而在一个或多个Client中包含对象A的引用,Client通过该引用可以调用远端Server中对象A的接口函数,这种远端调用对Client而言,与调用本地对象并无区别。


通信模型


Binder机制定义了四个组件,分别是ClientServerServiceManagerbinder驱动,其中Client,ServerServiceManager运行于用户空间,binder驱动运行于内核空间。


binder驱动


binder驱动是内核中的一个字符设备驱动/dev/binder,它是整个Binder通信机制的核心。Client,Server,ServiceManager通过open()ioctl()文件操作函数与binder驱动进行通信,从而实现了ClientServer发送请求,Server处理请求并返回结果到Client。具体来说,它负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。


ServiceManager

ServiceManager是一个守护进程,负责管理服务,即所有的Server需要向ServiceManager注册服务。同时,ServiceManagerClient提供查询和获取Server的接口。


binder通信实例


实现一个binder通信实例,需要经过以下步骤:

1)获得ServiceManager的对象引用

2)向ServiceManager注册新的Service

3)在Client中通过ServiceManager获得Service对象引用

3)在Client中发送请求,由Service返回结果。


下面看具体的代码如何实现。


3.1 libmyservice代码实现


1)新建目录frameworks/base/myservice/libservice,进入该目录

  1. $ cd  frameworks/base  
  2. $ mkdir myservice  
  3. $ cd myservice  
  4. $ mkdir libmyservice  
  5. $ cd libmyservice  

2)编写libmyservice/myservic.h文件


  1. #include <utils/threads.h>    
  2.   
  3. #include <utils/RefBase.h>    
  4.   
  5. #include <binder/IInterface.h>    
  6.   
  7. #include <binder/BpBinder.h>    
  8.   
  9. #include <binder/Parcel.h>    
  10.   
  11.     
  12.   
  13. namespace android {    
  14.   
  15.     class MyService : public BBinder    
  16.   
  17.     {    
  18.   
  19.         mutable Mutex mLock;    
  20.   
  21.         int32_t mNextConnId;    
  22.   
  23.         public:    
  24.   
  25.             static int instantiate();    
  26.   
  27.             MyService();    
  28.   
  29.             virtual ~MyService();    
  30.   
  31.             virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);    
  32.   
  33.     };    
  34.   
  35. }; //namespace    

(2)编写libservice/myservice.cpp文件


  1. #include "myservice.h"    
  2.   
  3. #include <binder/IServiceManager.h>    
  4.   
  5. #include <binder/IPCThreadState.h>    
  6.   
  7.     
  8.   
  9. namespace android {    
  10.   
  11.     
  12.   
  13.     static struct sigaction oldact;    
  14.   
  15.     static pthread_key_t sigbuskey;    
  16.   
  17.         
  18.   
  19.     int MyService::instantiate()    
  20.   
  21.     {    
  22.   
  23.         LOGE("MyService instantiate");    
  24.   
  25.         // defaultServiceManager ()获得ServiceManager的对象引用,addService()可向ServiceManager注册新的服务  
  26.   
  27.         int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService());    
  28.   
  29.         LOGE("MyService r = %d/n", r);    
  30.   
  31.         return r;    
  32.   
  33.     }    
  34.   
  35.     
  36.   
  37.     MyService::MyService()    
  38.   
  39.     {     
  40.   
  41.         LOGV("MyService created");    
  42.   
  43.         mNextConnId = 1;    
  44.   
  45.         pthread_key_create(&sigbuskey, NULL);    
  46.   
  47.     }    
  48.   
  49.     
  50.   
  51.     MyService::~MyService()    
  52.   
  53.     {    
  54.   
  55.         pthread_key_delete(sigbuskey);    
  56.   
  57.         LOGV("MyService destroyed");    
  58.   
  59.     }    
  60.   
  61.     // 每个系统服务都继承自BBinder类,都应重写BBinder的onTransact虚函数。当用户发送请求到达Service时,系统框架会调用Service的onTransact函数,该函数分析接收到的数据包,调用相应的接口函数处理请求  
  62.   
  63.     status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)    
  64.   
  65.     {    
  66.   
  67.         switch(code)    
  68.   
  69.         {    
  70.   
  71.             case 0: {    
  72.   
  73.                 pid_t pid = data.readInt32();    
  74.   
  75.                 int num   = data.readInt32();    
  76.   
  77.                 num = num + 100;    
  78.   
  79.                 reply->writeInt32(num);    
  80.   
  81.                 return NO_ERROR;    
  82.   
  83.                 }    
  84.   
  85.                 break;    
  86.   
  87.             default:    
  88.   
  89.                 return BBinder::onTransact(code, data, reply, flags);    
  90.   
  91.         }    
  92.   
  93.     }    
  94.   
  95. }; //namespace    

3)编写libservice/Android.mk文件


  1. # File: Android.mk    
  2. LOCAL_PATH := $(call my-dir)  
  3. include $(CLEAR_VARS)  
  4. LOCAL_SRC_FILES := myservice.cpp  
  5. LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)  
  6. LOCAL_SHARED_LIBRARIES := libutils libbinder  
  7. LOCAL_MODULE_TAGS := optional  
  8. LOCAL_PRELINK_MODULE := false  
  9. LOCAL_MODULE := libmyservice  
  10.   
  11. include $(BUILD_SHARED_LIBRARY)  

4)编译libmyservice.so动态库


android源码主目录下

  1. $ source build/envsetup.sh   
  2.   
  3. including device/htc/passion/vendorsetup.sh  
  4.   
  5. including device/samsung/crespo4g/vendorsetup.sh  
  6.   
  7. including device/samsung/crespo/vendorsetup.sh  
  8.   
  9.   
  10. $ mmm frameworks/base/myservice/libmyservice/  

编译成功后生成文件:out/target/product/generic/system/lib/libmyservice.so


3.2 myserver代码实现


1)新建目录myservice/myserver,并进入该目录


2)编写myserver/myserver.cpp文件


  1. #include <sys/types.h>    
  2.   
  3. #include <unistd.h>    
  4.   
  5. #include <grp.h>    
  6.   
  7. #include <binder/IPCThreadState.h>    
  8.   
  9. #include <binder/ProcessState.h>    
  10.   
  11. #include <binder/IServiceManager.h>    
  12.   
  13. #include <utils/Log.h>    
  14.   
  15. #include <private/android_filesystem_config.h>    
  16.   
  17. #include "../libmyservice/myservice.h"    
  18.   
  19.     
  20.   
  21. using namespace android;    
  22.   
  23.     
  24.   
  25. int main(int argc, char** argv)    
  26.   
  27. {    
  28.   
  29.     sp<ProcessState> proc(ProcessState::self());   
  30.   
  31.     sp<IServiceManager> sm = defaultServiceManager();//获得ServiceManager接口    
  32.   
  33.     LOGI("ServiceManager: %p", sm.get());    
  34.   
  35.     MyService::instantiate();    
  36. //执行addService()函数,注册服务  
  37.     ProcessState::self()->startThreadPool();    
  38.   
  39.     IPCThreadState::self()->joinThreadPool();    
  40. //进入循环,等待客户端的请求  
  41.     return 0;    
  42.   
  43. }    

(3)编写myserver/Android.mk文件


  1. # File: Android.mk  
  2.   
  3. LOCAL_PATH:= $(call my-dir)  
  4.   
  5. include $(CLEAR_VARS)  
  6.   
  7. LOCAL_SRC_FILES:= \  
  8.   
  9.     myserver.cpp  
  10.   
  11. LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)  
  12.   
  13. LOCAL_SHARED_LIBRARIES := \  
  14.   
  15.     libutils libbinder libmyservice  
  16.   
  17. LOCAL_MODULE_TAGS := optional  
  18.   
  19. LOCAL_PRELINK_MODULE := false  
  20.   
  21. LOCAL_MODULE := myserver  
  22.   
  23.   
  24.   
  25. include $(BUILD_EXECUTABLE)  

4)编译myserver可执行程序

android源码主目录下执行:

  1. $mmm frameworks/base/myservice/myserver/  

编译成功后生成文件:out/target/product/generic/symbols/system/bin/myserver


3.3 MyClient客户端代码实现


1)新建目录myservice/myclient,进入该目录


2)编写myclient/myclient.h文件


  1. namespace android  
  2.   
  3. {  
  4.   
  5.     class MyClient {  
  6.   
  7.     public:  
  8.   
  9.         void add100(int n);  
  10.   
  11.         private:  
  12.   
  13.         static const void getMyService();  
  14. //通过ServiceManager获取服务接口  
  15.     };  
  16.   
  17. }; //namespace   

3)编写myclient/myclient.cpp文件


  1. #include <binder/IServiceManager.h>  
  2.   
  3. #include <binder/IPCThreadState.h>  
  4.   
  5. #include "myclient.h"  
  6.   
  7.   
  8.   
  9. namespace android  
  10.   
  11. {  
  12.   
  13.     sp<IBinder> binder;  
  14.   
  15.     void MyClient::add100(int n)  
  16.   
  17.     {  
  18.   
  19.         getMyService();  
  20.   
  21.         Parcel data, reply;  
  22.   
  23.         int answer;  
  24.   
  25.           
  26.   
  27.         data.writeInt32(getpid());  
  28.   
  29.         data.writeInt32(n);  
  30.   
  31.         LOGE("BpMyService::create remote()->transact()/n");  
  32.   
  33.         binder->transact(0, data, &reply);  
  34.   
  35.         answer = reply.readInt32();  
  36.   
  37.         printf("answner=%d/n", answer);      
  38.   
  39.         return;  
  40.   
  41.     }  
  42.   
  43.   
  44.   
  45.     const void MyClient::getMyService()  
  46.   
  47.     {  
  48.   
  49.         sp<IServiceManager> sm = defaultServiceManager();  
  50.   
  51.         binder = sm->getService(String16("android.myservice"));  
  52.   
  53.         LOGE("MyClient::getMyService %p/n",sm.get());  
  54.   
  55.         if (binder == 0) {  
  56.   
  57.             LOGW("MyService not published, waiting...");  
  58.   
  59.         return;  
  60.   
  61.         }  
  62.   
  63.     }  
  64.   
  65. }; //namespace  
  66.   
  67.   
  68.   
  69. using namespace android;  
  70.   
  71.   
  72.   
  73. int main(int argc, char** argv)  
  74.   
  75. {  
  76.   
  77.     MyClient* p = new MyClient();  
  78.   
  79.     p->add100(1);  
  80.   
  81.     return 0;  
  82.   
  83. }  

(4)编写myclient/Android.mk文件


  1. LOCAL_PATH:= $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_SRC_FILES:= \  
  6.   
  7.     myclient.cpp  
  8.   
  9. LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)  
  10.   
  11. LOCAL_SHARED_LIBRARIES := \  
  12.   
  13.     libutils libbinder libmyservice  
  14.   
  15. LOCAL_MODULE_TAGS := optional  
  16.   
  17. LOCAL_PRELINK_MODULE := false  
  18.   
  19. LOCAL_MODULE := myclient  
  20.   
  21.   
  22.   
  23. include $(BUILD_EXECUTABLE)  

5)编译myclient可执行程序


android源码主目录下,执行:

  1. $ mmm frameworks/base/myservice/myclient/  

编译成功后生成可执行文件:out/target/product/generic/symbols/system/bin/myclient


3.4在模拟器上运行


1)启动模拟器


  1. $ cd ~/software/android/android-sdk-linux/tools  
  2. $ ./emulator -avd gbread -partition-size 512  

2)拷贝libmyservice.so到模拟器的/system/lib目录


  1. $cd out/target/product/generic/obj/lib  
  2. $adb remount  
  3. $ adb push libmyservice.so /system/lib  
  4.   
  5. 159 KB/s (10084 bytes in 0.061s)  

(3)拷贝myserver到模拟器的/system/bin目录


  1. $cd out/target/product/generic/symbols/system/bin  
  2. $ adb push myserver /system/bin  
  3.   
  4. 668 KB/s (27508 bytes in 0.040s)  

(4)拷贝myclient/system/bin目录


  1. $ adb push myclient /system/bin  
  2.   
  3. 1549 KB/s (46840 bytes in 0.029s)  

5)在模拟器上启动服务,并执行客户端程序。


  1. # adb shell  
  2. # cd system/bin  
  3. # ls my*  
  4.   
  5. myclient  
  6.   
  7. myserver  
  8.   
  9. # ./myserver  
  10. # ./myclient  
  11. 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



猜你喜欢

转载自blog.csdn.net/w_xue/article/details/42926819