android面试(6)-Binder机制

一直说,要写一篇关于Binder的详解,今天终于发福利了~

说到Binder,真的是头大,因为它涉及到的知识点实在是太多,所以在这里,我不准备总结太底层的东西,原因嘛,就是因为我也还没搞清楚,哈哈~~;

好了,言归正传,要想了解Binder,首先得了解一些Linux内核的基础知识:

1.Linux内核基础知识:

(1)用户空间/内核空间:

一切从简,用户空间指的是用户程序所运行的空间,内核空间是 Linux 内核的运行空间,为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。

(2)系统调用

Linux将用户空间和内核空间隔离是有其道理的,用户软件良莠不齐,要是它们乱搞把系统玩坏了怎么办?因此对于某些特权操作必须交给安全可靠的内核来执行。

但是虽然是隔离的,但是总有一些用户软件需要访问内核空间,比如应用程序访问文件,网络是很常见的事情,怎么办呢?

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

(3)Binder驱动:

通过系统调用,用户空间可以访问内核空间,那么如果一个用户空间想与另外一个用户空间进行通信怎么办呢?很自然想到的是让操作系统内核添加支持;传统的 Linux 通信机制,比如 Socket,管道等都是内核支持的;但是 Binder 并不是 Linux 内核的一部分,它是怎么做到访问内核空间的呢? Linux 的动态可加载内核模块(Loadable Kernel Module,LKM)机制解决了这个问题;模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。这样,Android系统可以通过添加一个内核模块运行在内核空间,用户进程之间的通过这个模块作为桥梁,就可以完成通信了。

在 Android 系统中,这个运行在内核空间的,负责各个用户进程通过 Binder 通信的内核模块叫做 Binder 驱动;

了解了这些概念之后,接下来正式进入Binder机制的介绍:

2.Binder机制:

首先我们思考一个问题:我们知道,Android使用的Linux内核拥有着非常多的跨进程通信机制,比如说,socket,管道之类的,那么为什么还要单独为Android创造一个Binder呢?

总结来说,有两个原因:

(1)出于性能上的考虑:Android是移动设备,相比于PC机的性能会有差距,在移动设备上进行频繁的跨进程通信本身就是一个极大的考验,Binder相比较于传统的socket/管道通信而言,更加高效,它在IPC时,只需要数据拷贝1次,而传统的socket之类的需要2次;

(2)出于安全上的考虑:传统的进程间通信对于通信双方的身份没有进行严格的验证,只有上层协议才会进行架构,比如说,socket通信时,IP地址是手动填写的,可以进行人为的伪造,而Binder支持通信双方进行身份校验,极大的保障了安全性;

第二,我们来谈一谈Binder的通信模型:

我们其实可以进程通信的双方一方称为服务端进程,另一方称为客户端进程,我们知道,由于进程隔离的存在,在不进行进程间通信的方式的情况下,客户端进程是无法访问服务端进程的;

可以举个例子:A和B要打电话,A首先要有B的电话号码,电话号码在通信录获取,通信录中保存了B的昵称,电话号码之类的信息,得到电话号码之后,还需要电话基站的支持,A和B才可以进行电话交流;这里,我们发现,一次简单的打电话的过程,除了A和B两个主体对象外,还存在两个隐含的但是必不可少的东西,通信录和电话基站;

从上面的基础知识我们可以知道,两个进程之间如果需要进行通信,那么就必须需要内核的帮助,而这个内核模块就是Binder驱动。

我们可以做个类比,对于A和B相当于两个进程,他们要打电话就相当于要进行通信,其中电话基站就想到与Binder驱动,而通信录则相当于其中的一个ServerManager

ServerManager其实就是一个进程,它里面维护了一张表,表里面存储的是向他注册过的进程信息,在通信之初,首先需要有一个进程向驱动申请成为ServerManager,当内核驱动同意之后,这个成为ServerManager的进程就负责管理所有需要通信的进程信息,当客户端进程要访问服务端进程时,服务端进程首先会向ServerManager注册,让ServerManager保存自己的有关信息,当ServerManger保存完毕后,客户端进程就会通过Binder驱动向ServerManger查询服务端进程的信息,ServerManage就会将服务端进程的信息返回给客户端进程,客户端与服务端进程之间就可以通过这些信息,利用Binder驱动来进行通信了;

所以,总结来说,Binder通信机制分三步:

第一步:ServerManager在其内部维护一张表;

第二步:服务端进程向ServerManager注册信息;

第三步:客户端进程向ServerManager取得信息,通过Binder驱动与服务端进程通信;


这里我们一直强调通过Binder驱动进行通信,但是Binder的通信原理到底是什么呢?这里有点绕。

如上图,客户端想调用服务端的的add方法,返回一个Object对象

首先,Server会先向SeverManager注册一张表,这个表中就存储了相关信息,告诉ServerManager我这里有一个返回值为Object的add方法,

client向ServerManager中查询Server端有没有一个返回值为Object的add方法,由于进程之间的通信都是在内核中进行的,驱动会在数据传输时做一些手脚,不会返回给client真正的server的Object的对象,而是返回一个代理对象,这个代理对象里包含了一个add方法,要注意,代理对象的add方法是一个空方法,它唯一要做的只是需要将参数包装好之后交给内核驱动来实现

Binder驱动收到代理对象的add方法之后,会在ServerManager表中查询存在有这个方法,Binder驱动就会将代理对象替换成server端的对象,调用server端的add方法,将结果返回给客户端。

Binder机制知识我还没有讲的很精细,但是大致轮廓差不多有了,最后,说了这么久,到底什么是Binder呢?在我看来啊,大致有三种角度来理解:

(1)通常意义上来说,Binder就是指Andriod的通信机制;

(2)对于服务端进程来说,Binder指的是Binder本地对象,对于客户端进程来说,Binder指的是Binder代理对象。

(3)对于传输过程来说,Binder是可以进行跨进程传递的对象;

转自:https://blog.csdn.net/pgg_cold/article/details/79393839

一直说,要写一篇关于Binder的详解,今天终于发福利了~

说到Binder,真的是头大,因为它涉及到的知识点实在是太多,所以在这里,我不准备总结太底层的东西,原因嘛,就是因为我也还没搞清楚,哈哈~~;

好了,言归正传,要想了解Binder,首先得了解一些Linux内核的基础知识:

1.Linux内核基础知识:

(1)用户空间/内核空间:

一切从简,用户空间指的是用户程序所运行的空间,内核空间是 Linux 内核的运行空间,为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。

(2)系统调用

Linux将用户空间和内核空间隔离是有其道理的,用户软件良莠不齐,要是它们乱搞把系统玩坏了怎么办?因此对于某些特权操作必须交给安全可靠的内核来执行。

但是虽然是隔离的,但是总有一些用户软件需要访问内核空间,比如应用程序访问文件,网络是很常见的事情,怎么办呢?

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

(3)Binder驱动:

通过系统调用,用户空间可以访问内核空间,那么如果一个用户空间想与另外一个用户空间进行通信怎么办呢?很自然想到的是让操作系统内核添加支持;传统的 Linux 通信机制,比如 Socket,管道等都是内核支持的;但是 Binder 并不是 Linux 内核的一部分,它是怎么做到访问内核空间的呢? Linux 的动态可加载内核模块(Loadable Kernel Module,LKM)机制解决了这个问题;模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。这样,Android系统可以通过添加一个内核模块运行在内核空间,用户进程之间的通过这个模块作为桥梁,就可以完成通信了。

在 Android 系统中,这个运行在内核空间的,负责各个用户进程通过 Binder 通信的内核模块叫做 Binder 驱动;

了解了这些概念之后,接下来正式进入Binder机制的介绍:

2.Binder机制:

首先我们思考一个问题:我们知道,Android使用的Linux内核拥有着非常多的跨进程通信机制,比如说,socket,管道之类的,那么为什么还要单独为Android创造一个Binder呢?

总结来说,有两个原因:

(1)出于性能上的考虑:Android是移动设备,相比于PC机的性能会有差距,在移动设备上进行频繁的跨进程通信本身就是一个极大的考验,Binder相比较于传统的socket/管道通信而言,更加高效,它在IPC时,只需要数据拷贝1次,而传统的socket之类的需要2次;

(2)出于安全上的考虑:传统的进程间通信对于通信双方的身份没有进行严格的验证,只有上层协议才会进行架构,比如说,socket通信时,IP地址是手动填写的,可以进行人为的伪造,而Binder支持通信双方进行身份校验,极大的保障了安全性;

第二,我们来谈一谈Binder的通信模型:

我们其实可以进程通信的双方一方称为服务端进程,另一方称为客户端进程,我们知道,由于进程隔离的存在,在不进行进程间通信的方式的情况下,客户端进程是无法访问服务端进程的;

可以举个例子:A和B要打电话,A首先要有B的电话号码,电话号码在通信录获取,通信录中保存了B的昵称,电话号码之类的信息,得到电话号码之后,还需要电话基站的支持,A和B才可以进行电话交流;这里,我们发现,一次简单的打电话的过程,除了A和B两个主体对象外,还存在两个隐含的但是必不可少的东西,通信录和电话基站;

从上面的基础知识我们可以知道,两个进程之间如果需要进行通信,那么就必须需要内核的帮助,而这个内核模块就是Binder驱动。

我们可以做个类比,对于A和B相当于两个进程,他们要打电话就相当于要进行通信,其中电话基站就想到与Binder驱动,而通信录则相当于其中的一个ServerManager

ServerManager其实就是一个进程,它里面维护了一张表,表里面存储的是向他注册过的进程信息,在通信之初,首先需要有一个进程向驱动申请成为ServerManager,当内核驱动同意之后,这个成为ServerManager的进程就负责管理所有需要通信的进程信息,当客户端进程要访问服务端进程时,服务端进程首先会向ServerManager注册,让ServerManager保存自己的有关信息,当ServerManger保存完毕后,客户端进程就会通过Binder驱动向ServerManger查询服务端进程的信息,ServerManage就会将服务端进程的信息返回给客户端进程,客户端与服务端进程之间就可以通过这些信息,利用Binder驱动来进行通信了;

所以,总结来说,Binder通信机制分三步:

第一步:ServerManager在其内部维护一张表;

第二步:服务端进程向ServerManager注册信息;

第三步:客户端进程向ServerManager取得信息,通过Binder驱动与服务端进程通信;


这里我们一直强调通过Binder驱动进行通信,但是Binder的通信原理到底是什么呢?这里有点绕。

如上图,客户端想调用服务端的的add方法,返回一个Object对象

首先,Server会先向SeverManager注册一张表,这个表中就存储了相关信息,告诉ServerManager我这里有一个返回值为Object的add方法,

client向ServerManager中查询Server端有没有一个返回值为Object的add方法,由于进程之间的通信都是在内核中进行的,驱动会在数据传输时做一些手脚,不会返回给client真正的server的Object的对象,而是返回一个代理对象,这个代理对象里包含了一个add方法,要注意,代理对象的add方法是一个空方法,它唯一要做的只是需要将参数包装好之后交给内核驱动来实现

Binder驱动收到代理对象的add方法之后,会在ServerManager表中查询存在有这个方法,Binder驱动就会将代理对象替换成server端的对象,调用server端的add方法,将结果返回给客户端。

Binder机制知识我还没有讲的很精细,但是大致轮廓差不多有了,最后,说了这么久,到底什么是Binder呢?在我看来啊,大致有三种角度来理解:

(1)通常意义上来说,Binder就是指Andriod的通信机制;

(2)对于服务端进程来说,Binder指的是Binder本地对象,对于客户端进程来说,Binder指的是Binder代理对象。

(3)对于传输过程来说,Binder是可以进行跨进程传递的对象;

猜你喜欢

转载自blog.csdn.net/u013651026/article/details/87883416
今日推荐