0. 虚拟地址与物理地址

在和群里的小伙伴沟通的过程中发现许多同学关于计算机组成和操作体系这块根底了解的比较少,所以我觉得有必要简单科普一下虚拟地址和物理地址。

操作体系内核一般以页为单位办理物理内存,一页的巨细一般是 4k 即 4096个Byte。为便利办理,一般会给这些页编一个号, 0,1,2,3,4。0 1 2 3 4 仅仅举例,实际不一定是。

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

关于进程而言,他拜访的内存地址不是物理地址而是一个虚拟的地址空间。

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

一样经过页的方式办理,一样的编号。

当咱们请求内存的时候,(c语言一般是 malloc 函数, c++ java 一般是经过关键字 new),比方 new Integer() ,操作体系先在虚拟地址空间找到一个闲暇页比方 2 号页,然后在物理地址找到闲暇页 比方 0 号页

找到今后,会将这个对应关系放到一个表中记载,这个表一般便是常说的 MMU 单元(内存办理单元)。

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

为什么要搞虚拟地址和 mmu,由于操作体系是多进程的,假如没有虚拟地址,多个进程的物理内存拜访会变得难以办理。有了虚拟地址今后,每个进程看到的都是完整的干净的地址空间。内存的办理扔给了操作体系,简化了应用程序的开发。

以上便是一个便于理解的简化的内存办理的模型,实际情况要杂乱一些,触及了分段分页,一二级页表,快表等内容,更为详细的内容能够参阅计算机组成,操作体系相关的书籍

1. Binder 是什么?

在 linux 中,每个进程都有自己的虚拟内存地址空间。虚拟内存地址空间又分为了用户地址空间和内核地址空间。

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

不同进程之间用户地址空间的变量和函数是不能彼此拜访的。

许多时候,提供体系功能的数据和函数都会放在固定的几个进程中(比方显示画面,播放声音等),咱们编写的用户程序要完结相应的功能就需求经过跨进程通讯技能来拜访这些数据和函数。

2. 完结跨进程通讯的思路

虽然用户地址空间是不能互相拜访的,但是不同进程的内核地址空间是相同和同享的,咱们能够凭借内核地址空间作为中转站来完结进程间数据的传输。

详细的咱们在 B 进程使用 copy_from_user 将用户态数据 int a 复制到内核态,这样就能够在 A 进程的内核态中拜访到 int a

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

更进一步,能够在 A 进程中调用 copytouser 能够将 int a 从内核地址空间复制到用户地址空间。至此,咱们的进程 A 用户态程序就能够拜访到进程 B 中的用户地址空间数据 int a

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

3. 优化咱们的计划

为了拜访 int a ,需求复制两次数据。能不能优化一下?咱们能够经过 mmap 将进程 A 的用户地址空间与内核地址空间进行映射,让他们指向相同的物理地址空间:

学得懂的 Android Framework 教程——学穿 Binder 篇之 Binder 基本原理

完结映射后,B 进程只需调用一次 copyfromuser,A 进程的用户空间中就能够拜访到 int a了。这里就优化到了一次复制。

以上便是 binder 最基本的原理了。

总结

  • 跨进程通讯的需求普遍存在
  • binder 跨进程通讯核心原理是 copytouser 和 mmap