读书笔记——Binder通信原理与机制

Binder通信原理与机制

目录

1. 预备知识
2.传统Linux进程通信机制
3.Binder通信机制

# 预备知识

操作系统中进程之间,内存地址是不共享的,不同进程之间就像是平行世界,是不能直接通信的,这是一种保护机制。A进程和B进程之间的要进行数据交互就必须采用特殊机制—— IPC


操作系统从逻辑上将虚拟空间划分为用户空间(User Space)和内核空间(Kernel Space)。简单的说就是,内核空间(Kernel)是系统内核运行的空间,用户空间(User Space)是用户程序运行的空间。为了保证安全性,它们之间是隔离的。当用户空间需要访问内核空间的资源时,需要借助系统调用来实现:

copy_from_user() //将数据从用户空间拷贝到内核空间
copy_to_user() //将数据从内核空间拷贝到用户空间

在这里插入图片描述


#传统Linux进程通信机制

我们再来看看传统IPC通信机制

1.管道

管道可用于具有亲缘关系进程间的通信,是由内核管理的一个缓冲区,管道的一端连接一个进程的输出。这个进程会向管道中放入信息。
管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构
管道示意图
当管道中没有消息的话,读取消息的进程会等待,知道有进程放入消息;当管道放满了消息时,尝试放入消息的进程会等待,知道有消息被取出。

缺点:管道的缓存区大小比较有限,不适合Android大量进程通信


2.消息队列

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。

缺点: 信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信;


3.共享内存

共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址

无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快

缺点: 通信需要设计复杂的机制保证各个进程通讯有效性。进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决; 安全问题比较突出。


4.Socket

作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信;


# Binder通信机制

Binder的通信模型有4个角色:Binder Client、Binder Server、Binder Driver(Binder驱动)、ServiceManager。
Binder通信模型
可以看见ServiceManager、Binder Client、Binder Server处于不同的进程,他们三个都在用户空间,而Binder驱动在内核空间。

1. Binder通信机制

1、Server进程通过Binder驱动向ServiceManager注册信息,告诉ServiceManager我是谁,我有什么,我能做什么。比如 Server进程有一个computer对象,这个对象中有add()方法。

2、Client进程通过Binder驱动向ServerManager查询Server进程信息,表示想要调用Server进程的computer对象的add()方法。此时Binder驱动将Server进程的computer对象转换成computerProxy代理对象,并转发给Client进程。Client进程拿到的并不是真实的computer对象,而是一个代理对象,即computerProxy对象,这个代理对象也包含了add()方法,不过只是队参数进行一些包装而已。

3、当Client进程调用add方法,这个消息发送给Binder驱动,这时驱动发现,原来是computerProxy,那么Client进程应该是需要调用computer对象的add方法的,这时驱动通知Server进程,调用你的computer对象的add方法,将结果给我。然后Server进程就将计算结果发送给驱动,驱动再转发给Client进程,这时Client进程还蒙在了鼓里,他以为自己调用的是真实的computer对象的add方法,其实他只是调用了代理而已。不过Client最终还是拿到了计算结果。


2. Binder通信原理

理解了Binder进程通信的流程,我们具体来看看它的实现原理 动态内核可加载模块 && 内存映射

1、动态内存可加载模块

我们之前提到的传统Linux IPC机制如管道,Socket套接字都是属于内核的一部分,通过内核的支持来实现跨进程通信,但是Binder并不是Linux系统内核的一部分。得益于Linux的 动态内核可加载模块 机制,Android系统通过动态的将Binder驱动添加到内核空间链接到内核作为其一部分运行。


2、内存映射

传统的 IPC 机制如管道、消息机制、Socket 都是需要拷贝两次数据

copy_from_user() //将数据从用户空间拷贝到内核空间
copy_to_user() //将数据从内核空间拷贝到用户空间

(共享内存不需要拷贝数据),而Binder数据拷贝只需要一次。这涉及到内存映射

Binder机制中的内存映射是通过mmap() 来实现的,简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间。

一次完整的 Binder IPC 通信过程通常是这样:

  1. 首先 Binder 驱动在内核空间创建一个数据接收缓存区;
  2. 接着在内核空间开辟一块内核缓存区,建立内核缓存区内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区接收进程用户空间地址的映射关系;
  3. 发送方进程通过系统调用 copyfromuser() 将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值