如何在Android下使用Binder

1概述


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

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


2 通信模型


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

如何在Android下使用Binder_第1张图片

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,进入该目录

$ 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



你可能感兴趣的:(android,server,jni,Module,service,include)