Binder

Binder

Binder原理
https://blog.csdn.net/yiranfeng/article/details/105314445

内核空间
用户空间
binder讲清楚
https://juejin.im/post/6844903656131657736
一次拷贝:内存映射mmap
安全,有身份验证uid
C/S架构

  • 是APP和系统服务之间的通信工具,提供跨进程的消息传递。
  • 系统的内核空间是共享的,每个进程都可以访问,Binder驱动存在于内核空间
  • 每一个进程都有一个ProcessState对象,负责打开Binder驱动
  • 每一个线程都有一个IPCThreadState对象,通过talkWithDriver,将IPC数据写入驱动中

IPC数据,包含的指令信息会说明,我是要和Server端哪个service打交道,请连接它,并把我要给它的东西给它,我要它干的事情告诉它

Binder驱动有连接着Server所有的service能力,具体是怎么实现的

好像是通过ServiceManager启动之后,启动循环,处理Client端发过来的请求

跨进程方式

传统的Linux跨进程方式:管道,共享内存,socket
  • 通信不安全:因为Linux内核不存在一种校验双方身份的机制,android为每个APP分配了UID,是鉴别进程身份的重要标志,在内核中添加。传统的IPC由用户在数据包填入UID/PID,容易篡改
  • 稳定性好:基于C/S架构
  • 性能:socket传输效率低,开销大;管道采用存储/转发方式,至少2次拷贝;Binder只需要一次拷贝,性能仅次于共享内存
应用层方式

主要有intent,只支持Bundle支持的数据类型;
Messenger 支持一对多串行通信,用于发送消息及Bundle数据;
AIDL 功能强大,可调用服务端方法;
ContentProvider 主要支持进程间共享数据;
BroadCastReceiver 广播也可实现进程间通信,发送消息及数据

稳定性:上面说到共享内存的性能优于Binder,那为什么不采用共享内存呢,因为共享内存需要处理并发同步问题,容易出现死锁和资源竞争,稳定性较差。Socket虽然是基于C/S架构的,但是它主要是用于网络间的通信且传输效率较低。Binder基于C/S架构 ,Server端与Client端相对独立,稳定性较好

当有多个业务模块都需要AIDL来进行IPC,此时需要为每个模块创建特定的aidl文件,那么相应的Service就会很多。必然会出现系统资源耗费严重、应用过度重量级的问题。解决办法是建立Binder连接池,即将每个业务模块的Binder请求统一转发到一个远程Service中去执行,从而避免重复创建Service。
工作原理:每个业务模块创建自己的AIDL接口并实现此接口,然后向服务端提供自己的唯一标识和其对应的Binder对象。服务端只需要一个Service并提供一个queryBinder接口,它会根据业务模块的特征来返回相应的Binder对象,不同的业务模块拿到所需的Binder对象后就可以进行远程方法的调用了。

进程隔离:进程和进程间内存是不共享的,要通信

https://blog.csdn.net/pange1991/article/details/84770181//操作系统进程的分配
https://juejin.im/post/5acccf845188255c3201100f//用户态和内核态

AIDL

我们来讲一下AIDL,它是Binder的封装JAVA API,应用层想要和Server端通信就可以直接使用AIDL了

AIDL支持的数据类型

基本数据类型(int、long、char 等)
String 和 CharSequence
List:只支持ArrayList,里面的每个元素都必须被AIDL支持。
Map: 只支持HashMap, 里面的每个元素都必须被AIDL支持。
Parcelable: 所有实现了Parcelable接口的对象
AIDL: 所有的AIDL接口本身也可以在AIDL文件中使用

server端

1、创建aidl文件aa.aidl,build之后在build/generated/source/aidl/debug路径生成aa.java,包含了一个抽象的内部类:stub,继承自Binder实现了aa接口,在stub内部,又创建了一个静态内部类Proxy,也实现了aa接口
然后
2、然后定义一个service,重写onBind方法

client端

1、将server端的aidl文件copy到client相同路径文件夹下,build生成java文件
bindService(intent,connection,Context.BIND_AUTO_CREATE),绑定成功之后,拿到server端传回的Binder对象,就可以调用到aa接口方法了

原理
asInterface(IBinder obj),将Binder对象转换成aa对象

1、client和server在同一个进程,直接返回stub对象,强转成aa对象,调用aa.aa()方法
2、client和server不是同一个进程,返回代理类prxoy对象。强转成aa对象,调用其实是proxy.aa()方法时,将参数和目标函数code写进Binder驱动中,并通过回调服务端Stub.onTransact()方法,实现调用真正的Stub.aa()方法
https://www.cnblogs.com/huangjialin/p/7738104.html

AIDL和Messenger的区别

Messenger不适用大量并发的请求:Messenger以串行的方式来处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端仍然只能一个个的去处理。
Messenger主要是为了传递消息:对于需要跨进程调用服务端的方法,这种情景不适用Messenger。
Messenger的底层实现是AIDL,系统为我们做了封装从而方便上层的调用。
AIDL适用于大量并发的请求,以及涉及到服务端端方法调用的情况

binder通信机制,binder如何被不同app进程使用的,binder如何启动?

zygote的runOnce()-zygoteInit()-nativeZygoteInit(),

再看看ProcessState::startThreadPool()函数,看看它是怎么启动线程池的

怎么启用binder机制

打开binder驱动

映射内存,分配缓冲区

注册binder线程

进入binder loop,不断的和binder驱动交互

问题:应用是怎么启用binder机制的?

1,什么时候启用binder机制,启用时机是什么,

说下AP启动流程

2,怎么启用binder机制,就是上面列出的4条

浅析逻辑地址与物理地址映射关系

https://blog.csdn.net/teemo_king/article/details/79133401

mmap内存映射原理
mmap是一种内存映射文件的方法,它将一个文件映射到进程的地址空间中,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。
实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。
相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享
https://blog.csdn.net/MakeContral/article/details/85170752

Android-内存映射mmap
https://blog.csdn.net/mcryeasy/article/details/86741781

为什么不直接用内存映射代替IO?

现在回到一开始的问题,既然内存映射可以提高文件的读取效率,为什么还要使用IO呢?

首先你要明白一点,直接将文件映射到虚拟内存,意味着没有数据没有缓存在内核缓存空间,而是直接读到了用户空间,
回想一下系统的IO和内核缓存搭配可以是的部分的文件使用效率更高。
而且从mmap的细节我们可以看到,映射的文件最好是大于4k的(一个内存页的大小),并且最好是4k的倍数。
也就是说两个方式都是有优缺点的,所以不存在代替这个说法,只能通过分析其场景而选择不同的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值