Binder是Android系统中实现进程间通信的核心机制,其本质是一种Proxy模式的具体实现,就像COM,CORBA一样。
Proxy模式的基本思想是客户端程序通过某种方式得到服务器端的代理对象,所有对服务器端的服务请求都发送给该代理对象,该代理对象负责同服务器端进行通信。从客户端的角度看,访问代理对象就如同访问其它本地对象一样;服务器代理对象则屏蔽了所有的进程间通信细节。
本文计划给出一个具体的例子,然后以这个例子为基础,深入剖析一下Android系统的绑定机制。
实例:新增加一个系统服务ExampleService,该服务可以接受一个整形参数,将其值加上100并返回。客户端应用程序使用此服务计算1+100的值。
代码1: 系统服务ExampleService的具体实现
view plain copy to clipboard print ?
-
- #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);
- };
- };
- #endif
view plain copy to clipboard print ?
-
- #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");
-
- 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");
- }
-
- 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);
- }
- }
- };
view plain copy to clipboard print ?
- # 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的应用程序
view plain copy to clipboard print ?
-
- #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());
- sp<IServiceManager> sm = defaultServiceManager();
- LOGI("ServiceManager: %p", sm.get());
- ExampleService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- return 0;
- }
view plain copy to clipboard print ?
- # 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的客户端应用程序
view plain copy to clipboard print ?
-
- #ifndef ANDROID_BYN_EXAMPLE_H
- #define ANDROID_BYN_EXAMPLE_H
-
- namespace android
- {
- class Example {
- public:
- void add100(int n);
- private:
- static const void getExampleService();
- };
- };
- #endif // ANDROID_BYN_EXAMPLE_H
view plain copy to clipboard print ?
-
- #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;
- }
- }
- };
-
- using namespace android;
-
- int main(int argc, char** argv)
- {
- Example* p = new Example();
- p->add100(1);
- return 0;
- }
view plain copy to clipboard print ?
- # 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