Binder进程间通信机制——概述

本篇文章是参照老罗的Blog整理而来。


Android应用程序是由ActivityServiceBroadcast ReceiverContent Provider四种类型的组件构成的,它们有可能运行在同一进程中,也有可能运行在不同的进程中。Android系统开发了一套新的进程间通信机制——Binder,方便那些运行在不同进程中的应用程序组件和系统组件进行通信。

Binder进程间通信机制采用了CS通信方式,其中,提供服务的进程称为Server进程,而访问服务的进程称为Client进程。Binder进程间通信机制主要涉及了ClientServiceService ManagerBinder驱动程序四个角色。

 

从上图中,可以得到如下信息:

1、Client、Server、Service Manager实现在用户空间,Binder驱动程序实现在内核空间中。

2、Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server。

3、Binder驱动程序提供设备文件 /dev/binder与用户空间交互,Client、Server和Service Manager通过系统调用open、mmap和ioctl来访问设备文件 /dev/binder。

4、Client和Server之间的进程间通信通过Binder驱动程序间接实现。

5、Service Manager是一个守护进程,用来管理server、并向Client提供查询Server接口的功能。

为了加深对Binder进程间通信机制的理解,分析了Binder进程间通信机制的四个使用场景,分别是:

1、Service Manager的启动过程。

2、Service Manager代理对象的获取过程。

3、Service组件的启动过程。

4、Service代理对象的获取过程。

 

 

Service Manager的启动过程

Service Manager是Binder进程间通信机制的核心组件之一,它扮演者Binder进程间通信机制上下文管理者的角色,同时负责管理系统中的Service组件,并且向Client组件提供获取Service代理对象的服务。

Service Manager是由init进程负责启动的,而init进程是在系统启动时启动的,因此,Service Manager也是在系统启动时启动的。

 

----Service Manager源代码目录结构

----Service_manager.c (frameworks\native\cmds\servicemanager)

----Binder.h (frameworks\native\cmds\servicemanager)

----Binder.c (frameworks\native\cmds\servicemanager)

 

从Service_manager.c的入口函数main(*)开启,Service Manager的启动过程主要分三个步骤:

1、调用函数binder_open打开设备文件 /dev/binder,以及将它映射到本进程的地址空间。

    bs = binder_open(128*1024);

2、调用函数binder_become_context_manager将自己注册为Binder进程间通信机制的上下文管理者。

    if (binder_become_context_manager(bs)) {

        ALOGE("cannot become context manager (%s)\n", strerror(errno));

        return -1;

    }

3、调用函数binder_loop来循环等待和处理Client进程的通信请求。

    binder_loop(bs, svcmgr_handler);

 

1、打开和映射Binder设备文件

--> Binder.c # binder_open(*)

具体过程如下:

1、调用函数open打开设备文件 /dev/binder;

    bs->fd = open("/dev/binder", O_RDWR);

2、调用函数mmap将设备文件 /dev/binder映射到进程的地址空间,它请求的地址空间大小正是binder_open接收的参数;

    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);

 

2、注册为Binder上下文管理者

--> Binder.c # binder_become_context_manager(*)

Service Manager要成为Binder进程间通信机制的上下文管理者,就必须要通过IO控制命令BINDER_SET_CONTEXT_MGR将自己注册到Binder驱动程序,这是通过调用函数binder_become_context_manager来实现的,该函数具体如下:

    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);

 

3、 循环等待Client进程请求

--> Binder.c # binder_loop(*)

由于Service Manager需要在系统运行期间为Service组件和Client组件提供服务,因此,它就需要通过一个无限循环来等待和处理Service组件和Client组件的进程间通信请求。

具体过程如下:

1、注册为Binder线程,以便Binder驱动程序即可将进程间通信请求分发给它处理。

    readbuf[0] = BC_ENTER_LOOPER;  /* Service Manager主线程是主动成为Binder线程 */

binder_write(bs, readbuf, sizeof(uint32_t));

2、通过IO控制命令BINDER_WRITE_READ来检查Binder驱动程序是否有新的进程间通信请求。

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

3、若有请求需要它处理,交给函数binder_parse来处理;否则,当前线程就会在Binder驱动程序中休眠等待。

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);

 

 

Service Manager代理对象的获取过程

Service组件在启动时,需要将自己注册到Service Manager中;而Client组件在使用Service组件提供的服务之前,也需要通过Service Manager来获得Service组件的代理对象。由于Service Manager本身是一个Service组件,因此,其他的Service组件和Client组件在使用它提供的服务之前,也需要先获得他的代理对象。

Service Manager远程接口是一个特殊的Binder引用,它的引用句柄一定是0。获取Service Manager远程接口的函数是defaultServiceManager。该函数声明在IServiceManager.h文件,实现在IServiceManager.cpp文件中。

 

——相关代码文件

——IServiceManager.h (frameworks\native\include\binder)

——IServiceManager.cpp (frameworks\native\libs\binder)

——Static.cpp (frameworks\native\libs\binder)

——ProcessState.cpp (frameworks\native\libs\binder)

——IInterface.h (frameworks\native\include\binder)

 

在Android系统的Binder机制中,Server和Client拿到的远程接口是指是BpServiceManager,包含了一个句柄值为0的Binder引用。

对于Server来说,就是调用IServiceManager::addService这个接口来和Binder驱动程序交互。而Client则调用IServiceManager::getService这个接口与Binder驱动程序交互。

 

 

Service组件的启动过程

Service组件是在Server进程中运行的。Server进程在启动时,会首先将它里面的Service组件注册到Service Manager中,接着再启动一个Binder线程池来等待和处理Client进程的通信请求。

 

Client进程和Service进程的一次进程间通信过程:

 

1、Client进程将进程间通信数据封装成一个Parcel对象,以便可以将进程间通信数据传递给Binder驱动程序。

2、Client进程向Binder驱动程序发送一个BC_TRANSACTION命令协议。Binder驱动程序根据协议内容找到目标Server进程之后,就会向Client进程发一个BR_TRANSACTION_COMPLETE返回协议,表示它的进程间通信请求已经被接收。Client进程接收到Binder驱动程序发送给它的BR_TRANSACTION_COMPLETE返回协议,并且对它进行处理,就会再次进入到Binder驱动程序中去等待目标Server进程返回进程间通信结果。

3、Binder驱动程序在向Client进程发送BR_TRANSACTION_COMPLETE返回协议的同时,也会向目标Server进程发送一个BR_TRANSACTION返回协议,请求目标Server进程处理该进程间通信请求。

4、Server进程接收到Binder驱动程序发来的BR_TRANSACTION返回协议,并且对它进行处理之后,就会向Binder驱动程序发送一个BC_REPLY命令协议。Binder驱动程序根据协议内容找到目标Client进程之后,就会向Server进程发送一个BR_TRANSACTION_COMPLETE返回协议,表示它返回的进程间通信结果已经收到了。Server进程接收到Binder驱动程序发给它的BR_TRANSACTION_COMPLETE返回协议,并且对它进行处理之后,以及进程间通信过程就此结束了。接着它会再次进入到Binder驱动程序中去等待下一次进程间通信请求。

5、Binder驱动程序向Server进程发送BR_TRANSACTION_COMPLETE返回协议的同时,也会向目标Client进程发送一个BR_REPLY返回协议,表示Server进程已经处理完成他的进程间通信请求了,并且将进程间通信结果返回给它。

 

 

Service代理对象的获取过程

Service组件将自己注册到Service Manager中之后,它就在Server进程中等待Client进程将进程间通信请求发送过来。Client进程为了和运行在Server进程中的Service组件通信,首先要获得它的一个代理对象,这是通过Service Manager提供的Service组件查询服务来实现的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值