Android系统启动篇
1,《android系统启动流程简介》
2,《android init进程启动流程》
3,《android zygote进程启动流程》
4,《Android SystemServer进程启动流程》
5,《android launcher启动流程》
6,《Android Activity启动过程详解》
Android系统开发准备篇
1,《Android 源码下载和编译》
2,《android 11源码编译和pixel3 刷机》
3,《Android Framework代码IDE加载和调试》
Android系统开发实践篇
1,《android设置默认输入法》
2,《android framework预制APK应用》
3,《Android系统层面限制应用开机自启动详解》
4,《android单独编译framework模块并push》
5,《Android Framework开发系统问题分析》
Android系统开发核心知识储备篇
1,《Android编译系统-envsetup和lunch代码篇》
2,《Android编译系统-概念篇》
3,《android日志系统详解》
4,《Android系统Handler详解》
5,《Android系统Binder详解》
6,《Android中Activity、View和Window关系详解》
7,《android view绘制流程详解》
8,《Android读取系统属性详解》
9,《android 窗口管理机制详解》
10,《初识Android系统》
11,《android中AMS进程通知Zygote进程fork新进程的通信方式》
Android核心功能详解篇
1,《android应用市场点击下载APK安装详解》
2,《Android 手势导航(从下往上滑动进入多任务页面)》
3,《android手势分析(应用界面左往右边滑动退出应用)》
4,《android应用安装流程详解》
5,《android11安装应用触发桌面图标刷新流程》
6,《Android系统多任务Recents详解》
7,《android系统导航栏视图分析》
———————————————————————————————————————————
目录
一,背景介绍
1.1 简介
1.2 核心概念
二,Binder原理
2.1 进程空间
2.2 Binder一次拷贝
2.3 Binder使用
2.4 Binder通信过程
三,实战
一,背景介绍
1.1 简介
Binder机制是Android系统提供的一种跨进程通信机制,它使用代理对象、共享内存和序列化等技术,实现了进程间通信和远程调用的功能。它允许在不同进程之间进行数据传输和方法调用,实现了进程间的解耦。在Android系统中,Binder被广泛应用于各种组件之间的通信,例如Activity与Service、Service与Service、应用与系统服务等。
1.2 核心概念
- 驱动层:Binder作为一个设备驱动存在于Linux内核中。当应用程序与Binder对象进行通信时,实际上是在与Binder驱动进行交互。Binder驱动负责管理Binder对象、传输数据以及进程间的上下文切换等工作。设备文件节点通常是
/dev/binder。
-
用户空间库:Binder提供了一套C++库和Java库,以方便用户空间的应用程序使用。这些库包括序列化/反序列化数据的工具、用于管理Binder对象的引用计数的工具以及在进程间调用方法时的代理(proxy)和存根对象(stub)等。在Java层,通常使用AIDL(Android Interface Definition Language)来定义跨进程接口。
-
代理与存根:Binder使用了代理(Proxy)和存根(Stub)对象来实现进程间的方法调用。当一个进程要调用另一个进程中的方法时,它会通过代理对象将方法调用转换为一个Binder事务。然后,这个事务会被发送到接收进程,由存根对象解析并执行对应的方法。最后,存根对象将结果返回给代理对象,完成整个跨进程调用。
-
序列化与反序列化:在进程间传输数据时,需要将数据序列化为字节流,以便在不同进程之间进行传输。在接收进程中,数据会被反序列化为原始格式。Binder提供了一套序列化和反序列化的工具(如Parcel类),用于在进程间传输数据。
-
引用计数与死亡通知:Binder机制通过引用计数来管理Binder对象的生命周期。当一个进程获得了另一个进程的Binder对象引用时,引用计数会增加。当引用计数减少到零时,Binder对象会被销毁。另外,Binder还支持死亡通知机制,允许一个进程监听另一个进程的Binder对象死亡事件。
二,Binder原理
2.1 进程空间
进程空间划分:用户空间(User Space) ——内核空间(Kernel Space)
1,每个Android的进程,只能运行在自己进程所拥有的虚拟地址空间。
2,对于用户空间,不同进程之间是不能共享的,而内核空间却是可共享的
3,Client进程向Server进程通信,恰恰是利用进程间可共享的内核内存空间来完成底层通信工作的
4,Client端与Server端进程往往采用ioctl等方法与内核空间的驱动进行交互。
2.2 Binder一次拷贝
Android 系统中用户进程间是如何通过内核模块(Binder 驱动)来实现通信的呢?当然不是之前的将数据从发送方进程拷贝到内核缓存区,然后再将数据从内核缓存区拷贝到接收方进程。而是通过内存映射:
1,内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间,映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间
2,反之内核空间对这段区域的修改也能直接反应到用户空间。内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动
Binder IPC 正是基于内存映射(mmap)来实现的,但是 mmap通常是用在有物理介质的文件系统上,进程中的用户区域是不能直接和物理设备打交道的。如果想要把磁盘上的数据读取到进程的用户区域,需要两次拷贝(磁盘–>内核空间–>用户空间),通常在这种场景下 mmap 就能发挥作用,通过在物理介质和用户空间之间建立映射,减少数据的拷贝次数,用内存读写取代I/O读写,提高文件读取效率。
副本直接copy进内核态映射给B用,那么什么是内存映射,
-
底层原理其实就是虚拟内存
-
简单来说:不同的虚拟内存指向相同的物理内存,从而实现共享内存和共享文件
一次完整的Binder IPC 通信过程通常是这样,
1,Binder 驱动在内核空间创建一个数据接收缓存区;
2,然后在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;
3,发送方进程通过系统调用 copy_from_user() 将数据拷贝到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
2.3 Binder使用
Binder通信的四个角色:
1,Client进程:使用服务的进程。
2,Server进程:提供服务的进程。
3,ServiceManager进程:ServiceManager的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。
4,Binder驱动:驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。
Binder通信采用c/s架构,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。
Server先向ServiceManager注册一个服务,其实也就是一个字符串。然后Client从ServiceManager获取服务,关键字就是注册的字符串。这样Client和Server就可以通信。真正的数据流是走了底层的Linux内核空间的binder驱动,但这个是被封装的,所以不用关心真正的binder驱动,只管在Client和Server之间调用函数收发数据就行。就是服务端的onTransact函数和客户端remote()->transact(TEST, data, &reply),发送的数据存在data中,返回的数据存在reply中。Client和Server都可以收发数据。
上图中Client、Server和ServiceManage之间的相互通信都是基于Binder机制。既然基于Binder机制通信,那么同样也是C/S架构,则图中的3大步骤都有相应的Client端与Server端。
1,注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端。
2,获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端。
3,使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:Client是客户端,Server是服务端。
上图中的Client,Server,Service Manager之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过与Binder驱动进行交互的,从而实现IPC通信(Interprocess Communication)方式。
其中Binder驱动位于内核空间,Client,Server,Service Manager位于用户空间。
Binder驱动和Service Manager可以看做是Android平台的基础架构,而Client和Server是Android的应用层,开发人员只需自定义实现Client、Server端,借助Android的基本平台架构便可以直接进行IPC通信。
Client、Server、ServiceManager、Binder 驱动 就如同互联网中服务器(Server)、客户端(Client)、DNS域名服务器(ServiceManager)以及路由器(Binder 驱动)之前的关系。
2.4 Binder通信过程
1、首先,一个进程使用 BINDERSETCONTEXT_MGR 命令通过 Binder 驱动将自己注册成为 ServiceManager;
2、Server 通过驱动向 ServiceManager 中注册 Binder(Server 中的 Binder 实体),表明可以对外提供服务。驱动为这个 Binder 创建位于内核中的实体节点以及 ServiceManager 对实体的引用,将名字以及新建的引用打包传给 ServiceManager,ServiceManger 将其填入查找表。
3、Client 通过名字,在 Binder 驱动的帮助下从 ServiceManager 中获取到对 Binder 实体的引用,通过这个引用就能实现和 Server 进程的通信。
三,实战
程序跨进程调用系统服务的简单示例,实现浮动窗口部分代码:
//获取WindowManager服务引用
WindowManager wm = (WindowManager) getSystemService(getApplication().WINDOW_SERVICE);
//布局参数layoutParams相关设置略...
View view = LayoutInflater.from(getApplication()).inflate(R.layout.float_layout, null);
//添加view
wm.addView(view, layoutParams);
1,注册服务(addService): 在Android开机启动过程中,Android会初始化系统的各种Service,并将这些Service向ServiceManager注册(即让ServiceManager管理)。这一步是系统自动完成的。
2,获取服务(getService): 客户端想要得到具体的Service直接向ServiceManager要即可。客户端首先向ServiceManager查询得到具体的Service引用,通常是Service引用的代理对象,对数据进行一些处理操作。即第2行代码中,得到的wm是WindowManager对象的引用。
3,使用服务: 通过这个引用向具体的服务端发送请求,服务端执行完成后就返回。即第6行调用WindowManager的addView函数,将触发远程调用,调用的是运行在systemServer进程中的WindowManager的addView函数。
1,Client通过获得一个Server的代理接口,对Server进行调用。
2,代理接口中定义的方法与Server中定义的方法是一一对应的。
3,Client调用某个代理接口中的方法时,代理接口的方法会将Client传递的参数打
包成Parcel对象。
4,代理接口将Parcel发送给内核中的Binder Driver。
5,Server会读取Binder Driver中的请求数据,如果是发送给自己的,解包Parcel
对象,处理并将结果返回。
6,整个的调用过程是一个同步过程,在Server处理的时候,Client会Block住。因
此Client调用过程不应在主线程。
————————————————
参考:Yawn__
原文链接:https://blog.csdn.net/ly0724ok/article/details/117566381/