Android的Binder机制浅析
1. 引言
一般实际的软件系统中进程间通信(IPC)的实现方法有命名管道(named pipe),共享内存(shared memory),消息队列(message queue),Socket等方法。在Android的框架(Framework)中,以Binder作为框架内进程间(通常如服务和客户间)通信的主要实现手段。这可能是出于效率和软件架构考虑。Binder通信的底层基础是Binder设备,本文通过一些实例简要介绍基于Binder通信的流程,由于整个机制,尤其是驱动和一些数据封装部分相当复杂,本文也仅仅关注了其主体的流程,难免有疏漏和错误。
2. Binder相关模块及其流程
Binder通信主要涉及以下文件:
进程状态对象:
include/utils/ProcessState.h, lib/utils/ProcessState.cpp
IPC通信机制和状态:
include/utils/IPCThreadState.h, lib/utils/ProcessState.cpp
Binder基础类:
include/utils/Binder.h,(以及一些派生类等)
(本文不加说明,相对目录均从/frameworks/base出发)
设备驱动模块:
Binder驱动模块位于Android根目录下/kernel/drivers/misc/binder.c中。
2.1 主要模块概览
图1显示了Framework中模块。其中XXX表示某具体应用。例如对Surface,其接口就是ISurface,本地调用端就是BpSurface,实现端就是BnSurface;对ServiceManager其接口就是IServiceManager,本地调用端就是BpServiceManager,实现端就是BnServiceManager。
图1 IPC-Binder相关对象继承关系
接口IXXX规定了这个应用需要实现的一些方法,例如ISurface中就定义了以下方法:
方法名 | 说明 |
registerBuffers | 注册Buffer |
postBuffer | 输送Buffer |
unregisterBuffers | 注销Buffer |
createOverlay | 创建叠层 |
以Surface应用为例,远端实现侧(进程)是一个Surface操作的具体实现。而在另一个具体的进程中只要通过创建和使用BpSurface,就能够调用这个远端进程的功能。
于是BpXXX,在这里即BpSurface,由于继承了ISurface,必须也实现这些方法。而通常BpXXX是本地调用远端具体实现的入口,因此在这其中通常是启动IPC,传入和传出数据和参数的过程,这其中mRemote(BpBinder对象)是媒介,详见后续讨论。
而BnXXX,即BnSurface,同样也继承了IServiceManager,也实现这些方法。而BnXXX(或其派生类),必须真正实现这些方法的具体工作,因为它是被BpXXX调用的。
又如SurfaceFlingerClient,其接口ISurfaceFlingerClient定义如下方法:
方法名 | 说明 |
getControlBlocks | 获得控制块 |
createSurface | 创建一个Surface对象(Bp, Bn侧) |
destroySurface | 销毁一个Surface对象 |
setState | 设置状态 |
而媒体播放器服务MediaPlayerService,其接口IMediaPlayerService定义如下方法:
方法名 | 说明 |
createMediaRecorer | 创建一个媒体录制器(MediaRecorder) |
createMetadataRetriever | 创建一个元数据读取器(MetadataRetriever) |
create | 创建一个媒体播放器(MediaPlayer) |
decode | 解码一个流 |
同样服务管理模块ServiceManager也是一个基于Binder的应用,接口IServiceManager定义了如下方法:
方法名 | 说明 |
getService | 获得一个服务 |
checkService | 查询服务 |
addService | 添加一个服务 |
listServices | 列举服务 |
2.2 Binder初始化
由于Binder的基础是Binder设备,因此设备的启动和配置是首要操作。
首先一个是Binder处理进程,它是android启动后第一个运行的binder相关程序。以下代码主要在cmds/serviceManager/binder.c中。以下是代码分析片段:
1: int main(int argc, char **argv)
2: {
3: struct binder_state *bs;
4: void *svcmgr = BINDER_SERVICE_MANAGER; //一个NULL指针
5:
6: bs = binder_open(mapsize = 128*1024)
7: {
8: …
9: bs->fd = open("/dev/binder", O_RDWR);
10: …
11: bs->mapsize = mapsize;
12: bs->mapped = mmap(NULL, mpasize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
13: …
14: }
15:
16: binder_become_context_manager(bs)
17: {
18: // 将本进程在内核中注册为context manager
19: ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
20: }
21:
22: svcmgr_handle = svcmgr;
23: binder_loop(bs, svcmgr_handler) // binder消息分发的关键循环
24: {
25: …
26: for(;;) {
27: …
28: // 一般阻塞再此,直到有消息送达(阻塞点1),详见激活点1
29: ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
30: {
31: …
32: binder_thread_write(…) { …}
33: binder_thread_read(…)
34: {
35: …激活后,相应处理中会在ptr所指buffer中将cmd设置为
36: BR_TRANSACTION
37: }
38: …
39: }
40:
41: // 解析消息
42: binder_parse(bs, bio = 0, ptr=readbuf, size = bwr.read_consumed,
43: func = svcmgr_handler)
44: {
45: while (解析readbuf未完)
46: {
47: cmd = *ptr++;
48: switch(cmd)
49: {
50: …
51: case BR_TRANSACTION:
52: func {=svcmgr_handler}(bs, txn, &msg, &reply)
53: {
54: …
55: switch(txn->code)
56: {
57: case SVC_MGR_GET_SERVICE: …
58: case SVC_MGR_CHECK_SERVICE: …
59: …
60: }
61: …
62: }
63: binder_send_reply(bs, &reply, txn->data, res)
64: {
65: data= …
66: binder_write(bs, &data, sizeof(data))
67: {
68: ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
69: }
70: }
71: }
72: }
73: }
74: }
75: }
76: return 0;
77: }
2.3 Runtime初始化
以下的服务进程和2.2介绍的类似,也是实现了ServiceManager的接口功能,只是它是用C++实现的,并且其本身也做成了Binder类型。
因此,它可能是在上述2.2初始化之后最先加入的服务,而此后它将服务于维护其他服务。同样它也注册成Context Manager,这样在客户侧调用时无需制定具体的对象句柄。
以下程序位于cmds/runtime/main_runtime.cpp。
1: int main(…)
2: {
3: …
4: boot_init()
5: {
6: proc = ProcessState::self();
7: proc->becomeContextManager(contextChecker, NULL)
8: {
9: …
10: // 本进程变为Context Manager,接受后续的Binder处理
11: ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
12: …
13: }
14:
15: sm = new BServiceManager;
16:
17: proc->setContextObject(IBinder object = sm)
18: {
19: setContextObject(sm, "default")
20: {
21: mContexts.add("default", sm)
22: {
23: 装入映射表mContexts中…
24: }
25: }
26: }
27: …
28: run(…)
29: {
30: …
31: IPCThreadState::self()->joinThreadPool()
32: {
33: 等待消息,过程类似2.7中的讨论
34: }
35: }
36: }
37: …
38: }
BServiceManager实现BnServiceManager,由于ServiceManager服务程序作为ContextManager,因此后续在defaultServiceManager()上进行IServiceManager调用(如调用getService())都将定向到这个对象,而BServiceManager则维护了系统中的所有服务。
2.4 Bp对象的创建
Bp相关类型在framework中通过宏定义实现。这个宏定义在include/utils/IInterface.h中以DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE命名。在相关的类定义中加入,例如在BpSurface这个例子中,它在ISurface.cpp中出现。
1: sp BpSurfaceFlingerClient::createSurface(..)
2: {
3: …
4: data上设置参数
5: mRemote->transact(CREATE_SURFACE, data, &reply)
6: {
7: … IPC调用到Bn侧功能并返回
8: }
9: …
10: sp binder = reply.readStrongBinder()
11: {
12: unflatten_binder(proc=ProcessState::self(), *this, sp* out = &val)
13: {
14: // 从in中取出flat_binder_object
15: flat_binder_object *flat = in.readObject(false);
16: if (flat)
17: {
18: switch(flat->type)
19: {
20: …
21: case BINDER_TYPE_HANDLE: // 本节注释1
22: *out = proc->getStrongProxyForHandle(flat->handle)
23: /* ProcessState:: getStrongProxyForHandle() */
24: {
25: // 查表获得一个表项,若首次则创建一个表项
26: e = lookupHandleLocked(handle);
27: if (e != NULL) {
28: IBinder * b = e->binder;
29: if (b == NULL || …)
30: { // 初次e->binder为空
31: e->binder = b = new BpBinder(handle)
32: { mHandle = handle; }
33: …
34: result = b;
35: }
36: }
37: return result;
38: }
39: return finish_unflatten_binder(NULL, *flat, in);
40: }
41: }
42: }
43: return val;
44: }
45: return interface_cast(binder) // 上述宏定义的展开
46: {
47: return sp ISurface::asInterface(binder)
48: {
49: sp intr;
50: if (binder != NULL)
51: {
52: …
53: intr = new BpSurface(binder)
54: {
55: 基类创建:BpRefBase(binder)
56: {
57: mRemote = binder.get(); // 即刚创建的BpBinder
58: }
59: }
60: }
61: }
62: }
63: }
可见BpSurfaceFlingerClient的作用之一是创建BpSurface对象。两者都在客户端(同一进程中)。
-----
【注释1】 在binder_transaction传递(ioctl在BINDER_WRITE_READ的BC_REPLY返回时,详见后续章节)中会将扁平处理的binder信息flat_binder_object中的类型从BINDER_TYPE_BINDER转换为BINDER_TYPE_HANDLE,而具体的handle是从底层对象注册用的红黑树上取出的唯一handle号,这样Bp侧用这个handle号和Bn侧的具体对象对应。
2.5 Bn对象的创建
而在Bn侧BnSurfaceFlingerClient::onTransact处理上述mRemote->transact的过程:
1: BnSurfaceFlingerClient::onTransact(…)
2: {
3: …
4: switch(code) {
5: case CREATE_SURFACE:
6: 从data上获取参数
7: sp s = BClient::createSurface(…)
8: {
9: …
10: 创建一个Bn侧的ISurface实体对象s
11: (BnSurface类型,具体如LayerBuffer::SurfaceBuffer)
12: …
13: sBinder = s->IInterface::asBinder()
14: {
15: BnInterface::onAsBinder()
16: {
17: return this;
18: }
19: }
20: reply->writeStrongBinder(sBinder)
21: {
22: flatten_binder(ProcessState::self(), binder= sBinder, out = this = reply)
23: {
24: flat_binder_object obj;
25: obj.flags = …
26: if (sBinder!= NULL)
27: {
28: local = binder->localBinder() { return this; }
29: if (!local)…
30: else
31: {
32: obj.type = BINDER_TYPE_BINDER;
33: obj.binder = local->getWeakRefs();
34: obj.cookie = local; // 这个在后续访问操作使用
35: }
36: }
37: … 其他分支略
38:
39: return finish_flatten_binder(sBinder, obj, out)
40: {
41: out->writeObject(obj, nullMetaData = false)
42: {
43: …将obj数据写到out这个Parcel对象中
44: }
45: }
46: }
47: }
48: // 此后reply这个Parcel将通过IPC传回客户端
49: }
50: …
51: }
52: }
上述客户端和远端代码基本展示了Surface的创建过程。Bp和Bn侧的Surface创建完成后才有后续Surface的具体运作。
2.6 BpSurface运作
以前面提到的ISurface上的postBuffer接口的工作为例。这部分将深一些到IPC 事务(transaction)作业内部。其实前一节的Surface的创建过程已经调用了ISurfaceFlingerClient::createSurface接口,已经走了一遍类似的transaction事务流程,而前一节主要以BpSurface和BnSurface为例介绍在IPC流程的前提——两侧的建立为目的,在这里再对此后的事务操作进行详细介绍。
从BpSurface出发:
1: void BpSurface::postBuffer(offset)
2: {
3: data.writeInterfacetoken(ISurface::getInterfaceDescriptor()); // ISurface接口描述符
4: data.writeInt32(offset);
5: mRemote->transact(code =POST_BUFFER, data, reply = &reply,
6: flags = IBinder::FLAG_ONEWAY) // FLAG_ONEWAY=1
7: (mRemote即刚才建立的BpBinder对象,即BpBinder::transact(..))
8: {
9: …
10: IPCThreadState::self()->transact(handle = mHandle, code, data, reply, flags)
11: { // handle是对应Bn侧Surface对象的有效值
12: …
13: writeTransactionData(cmd = BC_TRANSACTION, flags, handle,
14: code, data, NULL)
15: {
16: binder_transaction_data tr;
17: tr.target.handle = handle;
18: tr.code = code; tr.flags = flags;
19: ...
20: mOut.writeInt32(cmd)
21: mOut.write(&tr, sizeof(tr));
22: …
23: }
24: …
25: waitForResponse(reply = NULL, acquireResult = NULL) // 不需要返回值
26: {
27: while(1)
28: {
29: talkWithDriver()
30: {
31: …
32: ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
33: …
34: }
35: … 处理返回值
36: }
37: }
38: }
39: …
40: }
41: }
上述ioctl将调用请求做成通过Binder发送到远端。其过程在后续章节介绍。
2.7 Binder驱动概要
在/kernel/drivers/misc/binder.c的Binder设备驱动中,定义了以下函数,它在内核中处理上述ioctl调用,完成Binder的功能。
1: static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
2: {
3: …
4: // 以下将本函数调用者进程挂起(如上述BpSurface所在进程),直到处理完返回
5: wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
6:
7: // 进程私有数据
8: binder_proc proc = filp->private_data;
9: // 获得调用者进程的线程池数据结构
10: binder_thread *thread = binder_get_thread(proc);
11: …
12: switch(cmd)
13: {
14: case BINDER_WRITE_READ:
15: …
16: // 从用户空间将bind_write_read参数复制到bwr
17: copy_from_user(&bwr, ubuf, sizeof(bwr);
18: …
19: binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size,
20: bwr.write_consumed)
21: {
22: while (处理bwr.write_buffer未完成)
23: {
24: // 从用户空间获取cmd数据到内核空间
25: get_user(cmd, (uint32_t __user *)ptr);
26: …
27: switch(cmd)
28: {
29: …
30: case BC_TRANSACTION: case BC_REPLY:
31: // 从用户空间得到binder_transaction_data数据
32: copy_from_user(&tr, ptr, sizeof(tr));
33: …
34: binder_transaction(proc, thread, tr=&tr,
35: reply=(cmd==BC_REPLY)=false)
36: {
37: …
38: if (reply)
39: { // 是回复
40: …
41: }
42: else
43: { // 是正向请求
44: if (tr->target.handle)
45: { // 从红黑树中获得对应的节点
46: ref = binder_get_ref(proc, tr->target.handle);
47: …
48: target_node = ref->node;
49: }
50: else…
51: // 找到节点对应的服务进程
52: target_proc = target_node->proc;
53: …
54: }
55: if (target_thread) …
56: else
57: {
58: target_list = &target_proc->todo;
59: target_wait = &target_proc->wait;
60: }
61: …
62: for(遍历其中的flat objects)
63: {
64: …在postBuffer这个例子中忽略
65: …在createSurface中它将消息内含flat object进行处理
66: … 以实现两侧物件BINDER和HANDLE类型转换,
67: … 即完成2.4的注释1中的过程:
68: switch(fp->type)
69: {
70: …
71: case BINDER_TYPE_BINDER:
72: …
73: node=binder_new_node(proc,
74: ptr = fp->binder, cookie = fp->cookie)
75: {
76: …
77: node->proc = proc;
78: // 这个进程就是BnSurfaceFlingerClient和
79: // BnSurface所在进程
80: node->ptr = ptr;
81: node->cookie = cookie;
82: …
83: }
84:
85: …
86: binder_get_ref_for_node(target_proc, node);
87: …
88: fp->type = BINDER_TYPE_HANDLE;
89: …
90: }
91: }
92: …
93: // 激活点1:
94: // 唤醒进程(见“阻塞点2”)
95: // (对于在ServiceManager阶段会激活service_manager的“阻塞点1”)
96: wake_up_interruptible (target_wait);
97: } // binder_transaction
98: }
99: } // binder_thread_write
100: …
101: binder_thread_read(…)
102: {
103: … 读取数据
104: … 处理
105: if (t->buffer->target_node) {
106:
107: tr.target.ptr = target_node->ptr;
108: tr.cookie = target_node->cookie; //本地对象指针
109: … 相应处理中会在ptr所指buffer中将cmd设置为
110: BR_TRANSACTION
111: }
112: }
113: if (读得数据)
114: wake_up_interruptible(&proc->wait); //激活等数据的用户进程
115: }
116: …
117: // 反馈给用户空间
118: copy_to_usr(ubuf, &bwr, sizeof(bwr));
119: }
120: }
2.8 IPC处理和监听线程
以下Surface相关服务的进程入口(cmds/surfaceflinger/main_surfaceflinger.cpp):
1: int main(…)
2: {
3: …
4: SurfaceFlinger::instantiate()
5: { /* 实例化SurfaceFlinger服务 */
6: sm = defaultServiceManager()
7: {
8: if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
9: …
10: // 在当前进程中首次调用
11:
12: co = ProcessState::self()->getContextObject(NULL)
13: {
14: if (supportsProcess()) { /* Android支持此分支 */
15: return getStrongProxyForHandle(0)
16: {
17: 具体流程类似2.4节介绍,生成一个新的BpBinder对象
18: (ServiceManager的实际对象作为Context,功能实体在启
19: 动时已经产生,即2.3介绍的BServiceManager,所以此
20: 处不在需要生成Bn对象)
21: }
22: } else …
23: }
24: gDefaultServiceManager = interaface_cast(co)
25: {
26: …具体流程类似2.4节介绍,新建一个BpServiceManager对象
27: 上述BpBinder对象作为其mRemote
28: }
29: return gDefaultServiceManager;
30: }
31: sm->addService()
32: {
33: 远程调用,完成服务(SurfaceFlinger)的加载
34: }
35: }
36:
37: … 其他服务创建 …
38: ProcessState::self()->startThreadPool()
39: {
40: …
41: spawnPoolThread(true)
42: {
43: 创建线程运行IPCThreadState::self()->joinThreadPool(true)
44: }
45: }
46:
47: IPCThreadState::self()->joinThreadPool()
48: {
49: …
50: do {
51: …处理输入信息
52: talkWithDriver()
53: {
54: 通过ioctl和binder设备交换信息(见前几节介绍),
55: 数据未到时挂起(阻塞点2)
56: }
57: …
58: cmd = mIn.readInt32();
59: executeCommand(cmd)
60: {
61: switch(cmd)
62: {
63: …
64: case BR_TRANSACTION:
65: binder_transaction_data tr;
66: mIn.Read(&tr, sizeof(tr));
67: …
68: if (tr.target.ptr)
69: {
70: sp b = ((BBinder*)tr.cookie; // 本地对象指针
71: b->transact(tr.code, buffer, &reply, 0)
72: {
73: BnSurface:: onTransact(…)
74: {
75: switch(code)
76: {
77: …
78: case POST_BUFFER:
79: …
80: offset = data.readInt32();
81: postBuffer(offset);
82: …
83: }
84: …
85: }
86: }
87: }
88: …
89: }
90: }
91: } while (未完结);
92: …
93: }
94: }
以下是媒体相关服务进程入口:
1: int main(…)
2: {
3: …
4: MediaPlayerService::instantiate() { 见上一段代码 }
5: … 其他服务创建 …
6: ProcessState::self()->startThreadPool() { 见上一段代码 }
7: IPCThreadState::self()->joinThreadPool() { 见上一段代码 }
8: }
2.9 Surface总体流程
根据上述的Bp和Bn两侧生成过程原理分析SurfaceFlinger相关代码,可以发现:
通过ISurfaceFlinger::createConnection,两侧生成ISurfaceFlingerClient;
通过ISurfaceFlingerClient:: createSurface,两侧生成ISurface。
而服务SurfaceFlinger的Bp端最初通过获取服务取得,如下:
1: _get_surface_manager()
2: {
3: if (gSurfaceManager != 0) return gSurfaceManager;
4:
5: sm = defaultServiceManager() { 详见2.8节 }
6:
7: …
8: // 获得SurfaceFlinger服务(Bp侧句柄),其原理前面章节(如2.3节)
9: binder = sm->getService(String16("SurfaceFlinger"));
10: …
11:
12: // 实际产生
13: sp sc = interface_cast (binder)
14: { 详见2.4节,sc实为BpSurfaceComposer }
15:
16: if (gSurfaceManager == 0) gSurfaceManager = sc;
17:
18: return gSurfaceManager;
19: }
加上前述Surface的分析,Surface的总体服务流程如图2所示,这些操作使得最终在客户应用中得到BpSurfaceComposer, BpSurfaceFlingerClient和BpSurface三个对象。而发起这些创建的是客户就是SurfaceFlingerClient,它在SurfaceSession(Java对象)中维护,可见SurfaceSession是创建Surface的关键对象。
1: android_media_MediaPlayer_setDataSource(…) /* JNI */
2: {
3: sp mp = getMediaPlayer(…)
4: {
5: 获得Java对象中引用的MediaPlayer对象,
6: 它曾在android_media_MediaPlayer_native_setup中设置
7: 即一个新建的MediaPlayer对象。
8: 虽然它是BnMediaPlayer,但是接下来调用setDataSource将它绑定到一个远端
9: 的MediaPlayer上
10: }
11: MediaPlayer::setDataSource(url)
12: {
13: …
14: sp &service = MediaPlayer::getMediaPlayerService()
15: {
16: sp sm = defaultServiceManager() {…}
17: …
18: binder = sm->getService("media.player") {…}
19: …
20: sMediaPlayerService = interface_cast(binder)
21: { … 得到一个BpMediaPlayerService }
22: …
23: return sMediaPlayerService;
24: }
25: …
26: // 通过BpMediaPlayerService远程调用创建一个播放器
27: sp player = service->create(…) {…}
28: setDataSource(player)
29: {
30: …
31: mPlayer = player; // 远端的实际功能播放器
32: …
33: }
34: …
35: }
36: }
参考资料:
http://hi.baidu.com/albertchen521/blog/item/30c32d3f4bee993a71cf6ca0.html
http://www.limodev.cn/blog/archives/777