以一个具体的例子,深入剖析一下Android系统的绑定机制

转自 “http://blog.csdn.net/bigapple88/article/details/6579732

Binder是Android系统中实现进程间通信的核心机制,其本质是一种Proxy模式的具体实现,就像COM,CORBA一样。

    Proxy模式的基本思想是客户端程序通过某种方式得到服务器端的代理对象,所有对服务器端的服务请求都发送给该代理对象,该代理对象负责同服务器端进行通信。从客户端的角度看,访问代理对象就如同访问其它本地对象一样;服务器代理对象则屏蔽了所有的进程间通信细节。

    本文计划给出一个具体的例子,然后以这个例子为基础,深入剖析一下Android系统的绑定机制。

    实例:新增加一个系统服务ExampleService,该服务可以接受一个整形参数,将其值加上100并返回。客户端应用程序使用此服务计算1+100的值。

    代码1: 系统服务ExampleService的具体实现

// File: ExampleService.h
#ifndef ANDROID_EXAMPLE_SERVICE_H
#define ANDROID_EXAMPLE_SERVICE_H
#include <utils/threads.h>
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/BpBinder.h>
#include <binder/Parcel.h>

namespace android {
    class ExampleService : public BBinder
    {
        mutable Mutex mLock;
        int32_t mNextConnId;
        public:
            static int instantiate();
            ExampleService();
            virtual ~ExampleService();
            virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
	};
}; //namespace
#endif

// File: ExampleService.cpp
#include "ExampleService.h"
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>

namespace android {

    static struct sigaction oldact;
    static pthread_key_t sigbuskey;
    
    int ExampleService::instantiate()
    {
        LOGE("ExampleService instantiate");
        // 调用ServiceManager的addService方法进行系统服务注册,这样客户端程序就可以通过ServiceManager获得此服务的代理对象,从而请求其提供的服务
        int r = defaultServiceManager()->addService(String16("byn.example"), new ExampleService());
        LOGE("ExampleService r = %d/n", r);
        return r;
    }

    ExampleService::ExampleService()
    { 
        LOGV("ExampleService created");
        mNextConnId = 1;
        pthread_key_create(&sigbuskey, NULL);
    }

    ExampleService::~ExampleService()
    {
        pthread_key_delete(sigbuskey);
        LOGV("ExampleService destroyed");
    }
    // 每个系统服务都继承自BBinder类,都应重写BBinder的onTransact虚函数。当用户发送请求到达Service时,系统框架会调用Service的onTransact函数
    status_t ExampleService::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


# File: Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
	ExampleService.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
	libutils libbinder
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libExample

include $(BUILD_SHARED_LIBRARY)

在/framework/android/src/frameworks/base下面新建一个文件夹ExampleService,将以上三个文件复制到该文件夹中。


  代码2:启动ExampleService的应用程序

// File: ExampleServer.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 "../ExampleService/ExampleService.h"

using namespace android;

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());	// 要想使用Binder机制,必须要创建一个ProcessState对象
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    ExampleService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

# File: Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
	ExampleServer.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
	libutils libbinder libExample
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := ExampleServer

include $(BUILD_EXECUTABLE)


在/framework/android/src/frameworks/base下面新建一个文件夹ExampleServer,将以上两个文件复制到该文件夹中。

    代码3:使用ExampleService的客户端应用程序


// File: Example.h
#ifndef ANDROID_BYN_EXAMPLE_H
#define ANDROID_BYN_EXAMPLE_H

namespace android
{
    class Example {
    public:
        void add100(int n);
        private:
        static const void getExampleService();
    };
}; //namespace 
#endif // ANDROID_BYN_EXAMPLE_H


// File: Example.cpp
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "Example.h"

namespace android
{
    sp<IBinder> binder;
    void Example::add100(int n)
    {
        getExampleService();
        Parcel data, reply;
        int answer;
        
        data.writeInt32(getpid());
        data.writeInt32(n);
        LOGE("BpExampleService::create remote()->transact()/n");
        binder->transact(0, data, &reply);
        answer = reply.readInt32();
        printf("answner=%d/n", answer);    
        return;
    }

    const void Example::getExampleService()
    {
        sp<IServiceManager> sm = defaultServiceManager();
        binder = sm->getService(String16("byn.example"));
        LOGE("Example::getExampleService %p/n",sm.get());
        if (binder == 0) {
            LOGW("ExampleService not published, waiting...");
        return;
        }
    }
}; //namespace

using namespace android;

int main(int argc, char** argv)
{
    Example* p = new Example();
    p->add100(1);
    return 0;
}

# File: Example
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
	Example.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
	libutils libbinder libExample
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := Example

include $(BUILD_EXECUTABLE)

在/framework/android/src/frameworks/base下面新建一个文件夹Example,将以上三个文件复制到该文件夹中。

 

    Build整个Android系统,这里一共会在系统中生成三个文件,分别是

    /system/lib/libExample.so

    /system/bin/ExampleServer

    /system/bin/Example

 

    然后启动我们新添加的ExampleService系统服务,并启动客户端程序验证运行结果。

    $> adb shell

    # cd /system/bin

    # ./ExampleServer &

    # ./Example

    answer=101

 

    在接下来的几篇文章中,我们会以这个例子为基础,深入分析一下Android系统中Binder机制的各个部分。

 

 

    参考文献:

    1. 云中漫步博客:http://my.unix-center.net/~Simon_fu/

    2. 如何撰写自己的第一个核心服务--高焕堂:http://www.android1.net/Topic.aspx?BoardID=21&TopicID=990


你可能感兴趣的:(以一个具体的例子,深入剖析一下Android系统的绑定机制)