68

Android(IPC)进程间通讯1:详解Binder由来?

 5 years ago
source link: https://tryenough.com/android-ipc1?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Android开发的进程间通讯,整个Android的应用都依赖于binder做底层通信机制。而Linux中提供的进程间通讯方式并没有binder机制,那么android中为什么要单独创造这种通讯方式呢?带着这个问题,继续往下读。

Linux中进程相关概念

Linux将系统内存划分成了 用户空间内核空间 两部分:

j2YjmuV.png!web

用户空间 : 普通应用程序则运行在用户空间上,它们不能使用某些特定的系统功能,不能直接访问硬件,不能直接访问内核空间。

内核空间 : 系统的核心软件会运行在较高的特权级别上,它们驻留在被保护的内存空间上,拥有访问硬件设备的所有权限。

用户程序只能运行在用户空间,用户空间访问内核空间的唯一方式就是系统调用。

linux的用户程序和进程

在linux中,所有的用户程序执行时状态都是进程。进程间存在父子关系来表示同一个用户程序开启的多个同步任务。

所有的进程构成一个以 init 为根的树状结构,这是因为 Linux 内核 并不提供直接建立新进程的系统调用。剩下的所有进程都是 init 进程通过 fork 机制建立的。新的进程要通过老的进程复制自身得到,这就是 fork。fork 是一个系统调用。

每个进程都在内存中分配有属于自己的一片空间 (内存空间,包含栈、堆、全局静态区、文本常量区、程序代码区)。进程之间相互隔离资源:

  • 进程隔离是为保护进程之间互不干扰的执行。
  • 进程隔离技术使用了虚拟地址空间,即进程A的虚拟地址和进程B的虚拟地址不同,这样就防止进程A将数据信息写入进程B。

2Y7zEbN.png!web

因为进程隔离的原因,进程A和进程B之间不能直接进行通讯。

但是开发中,总难免要遇到进程通讯的地方(例如一个应用不通进程之间相互传递数据等场景)。

进程间通信方式(IPC)

虽然不同进程在用户空间不能直接进行通讯,但它们却是共享一份内核空间。很显然, 当一个用户进程想与另外一个用户进程进行通信时,就可以通过内核空间来完成了

Linux中常见的进程间通讯的几种方式:

nqyyi26.png!web

  • 1.管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
  • 2.信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);

  • 3.报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

  • 4.共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

  • 5.信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

  • 6.套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。

上面的6种都是内核里的程序:

进程A发起请求给内核里的程序,内核里的程序再将请求转发给进程B,从而达到进程间通信。

uqm2uqM.png!web

Android中的Binder诞生

Android系统通过Linux的动态可加载内核模块,添加一个内核模块运行在内核空间,用户进程之间的通过这个模块作为桥梁,就可以完成通信。就是我们后面要涉及到的:Binder驱动。

google通过新增内核模块完成了进程间通信协议的实现,然后使用binder驱动来调用这个新增的内核模块,来为上层应用提供接口,最后在framework层封装这个接口来提供 java API 调用接口。

Android系统为什么需要再实现一个进程间通信协议Binder呢?

  • 在移动设备上,Binder的传输效率和可操作性很好。
  • Binder机制能够很好地实现Client-Server架构。
  • Binder机制的安全性高。
    • 传统方式对于通信双方的身份并没有做出严格的验证,只有在上层协议上进行架设;
    • 比如Socket通信ip地址是客户端手动填入的,都可以进行伪造;
    • 而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。

感谢您的阅读,本系列会继续创作关于android中进程通讯的具体用法。欢迎前来观望。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK