Android -- 每日一问:什么是 Binder?它是如何实现跨进程通信的?

在这里插入图片描述

经典回答

Binder 模糊了进程边界,淡化了进程间通信的过程,整个系统仿佛运行于同一个面向对象的程序之中。

Linux进程基础
为了保护进程空间不被别的进程破坏或者干扰,Linux 的进程是相互独立的(进程隔离),而且一个进程空间还分为用户空间和内核(Kernel)空间,相当于把 Kernel 和上层的应用程序抽像的隔离开。这里有两个隔离,一个进程间是相互隔离的,二是进程内有用户和内核的隔离。

即然有隔离,那么它们之前要相互配合时就得有合作(交互)。进程间的交互就叫进程间通信(IPC,或称跨进程通信),而进程内的用户和内核的交互就是系统调用。

用户空间访问内核空间的唯一方式就是系统调用;通过这个统一入口接口,所有的资源访问都是在内核的控制下执行,以免导致对用户程序对系统资源的越权访问,从而保障了系统的安全和稳定。

也就是说,为了保证安全性和独立性,一个进程是不能直接操作或者访问别一个进程空间的。Android 即然是架设在 Linux 基础之上的,当然也要解决这个进程间通信的问题。

为什么要使用 Binder ?
在传统的 Linux 上,我们还是有很多选择可以用来实现进程间通信,如管道、SystemV、Socket 等。那么 Android 为什么不使用这些原有的技术,而是要使开发一种新的叫 Binder 的进程间通信机制呢?

主要有两个方面的原因:
1. 性能方面
在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder 相对出传统的 Socket 方式,更加高效。Binder 数据拷贝只需要一次,而管道、消息队列、Socket 都需要 2 次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。

2. 安全方面
传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如 Socket 通信 ip 地址是客户端手动填入,很容易进行伪造,而 Binder 机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。

还有一些好处,如实现面象对象的调用方式,在使用 Binder 时就和调用一个本地实例一样。

Binder 运行机制
Binder 基于 Client-Server 通信模式,除了 Client 端和 Server 端,还有两角色一起合作完成进程间通信功能。

扫描二维码关注公众号,回复: 14556575 查看本文章

Binder通信的四个角色:

  • Client进程:使用服务的进程。
  • Server进程:提供服务的进程。
  • ServiceManager 进程:ServiceManager 的作用是将字符形式的Binder名字转化成 Client 中对该 Binder 的引用,使得 Client 能够通过Binder名字获得对Server中Binder实体的引用。
  • Binder 驱动:驱动负责进程之间 Binder 通信的建立,Binder 在进程之间的传递,Binder 引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。

初次接触这些概念可能会觉得难于理解,读者可以把四个角色和熟悉的互联网进行类比:Server是服务器,Client是客户终端,ServiceManager是域名服务器(DNS),驱动是路由器。这样类比,你很容易就能理解下图:
image.png

Binder的运行机制就很好理解了,Server进程向Service Manager进程注册服务(可访问的方法接口),Client进程通过Binder驱动可以访问到Server进程提供的服务。Binder驱动管理着Binder之间的数据传递,这个数据的具体格式由Binder协议定义(可以类比为网络传输的TCP协议)。并且Binder驱动持有每个Server在内核中的Binder实体,并给Client进程提供Binder的引用。

Binder跨进程传输并不是真的把一个对象传输到了另外一个进程;传输过程好像是Binder跨进程穿越的时候,它在一个进程留下了一个真身,在另外一个进程幻化出一个影子(这个影子可以很多个);Client进程的操作其实是对于影子的操作,影子利用Binder驱动最终让真身完成操作。

image.png

Binder的线程管理
每个Binder的Server进程会创建很多线程来处理Binder请求,可以简单的理解为创建了一个Binder的线程池吧(虽然实际上并不完全是这样简单的线程管理方式),而真正管理这些线程并不是由这个Server端来管理的,而是由Binder驱动进行管理的。

一个进程的Binder线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程。理解这一点的话,你做进程间通信时处理并发问题就会有一个底,比如使用ContentProvider时(又一个使用Binder机制的组件),你就很清楚它的 CRUD(创建、检索、更新和删除)方法只能同时有16个线程在跑。

Binder对应用开发者的用处
上面提到的线程数是一个对应用开发有用的地方,很多人之前由于不了解有这个线程数的限制可能会在这里遇到过麻烦。

当然,最重要的是你了解了 Android 的进程间通信机制,知道Android的组件间是如何实现进程间通信和数据共享的,当你的应用要处理进程间通信时,你知道可能要关注哪个方面。如你的 Activity 组件可以设置在不同的进程中运行,那么每个进程都是独立的,它要使用别的进程的数据时,你就会知道用静态变量去交互没有意义。而且,理解了原理,再去编写 AIDL 的代码就没有那么难理解了。

对于一些 Framework 层的开发者,如自已定制 ROM 的团队,需要提供自己的系统服务时,Binder 机制肯定是必需要了解的,不然无从下手。

你的朋友是不是也在准备面试呢?你可以把今天的题目分享给好友,或许你可以帮到他。

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/128096611