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
本文详细介绍了Android中Binder的使用,包括其作为进程间通信机制的角色,通信模型的组成部分,如binder驱动和ServiceManager。通过一个完整的binder通信实例,展示了从创建libmyservice,实现myserver和MyClient,到在模拟器上运行的步骤,帮助读者理解Binder的实现过程。

被折叠的 条评论
为什么被折叠?



