开发者社区> jasmine_ben> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

android 进程间通信原理

简介: 前言 每个Android进程只能运行在自己拥有的虚拟地址空间,对于用户空间。不同进程之间彼此是不能共享的,而内核空间是可以共享的。Client和Server进程通信就是利用进程间可以共享内核内存空间来完成底层通信工作的,Client和Server通过ioctl等和内核空间进行交互。
+关注继续查看

前言

每个Android进程只能运行在自己拥有的虚拟地址空间,对于用户空间。不同进程之间彼此是不能共享的,而内核空间是可以共享的。Client和Server进程通信就是利用进程间可以共享内核内存空间来完成底层通信工作的,Client和Server通过ioctl等和内核空间进行交互。

img_2ce1f101ce30ad53f419410d3ac13485.png
进程通信架构

1、android的IPC和RPC

RPC指的是跨进程远程调用,强调了调用的功能,即一个进程之间调用另外一个进程的方法。

IPC指的是进程间通信,android使用Binder机制来进行进程间的通信,没有调用的功能。

Android系统的RPC = Binder进程间通信+在Binder基础上建立起来的进程间函数调用机制。

2、android系统的RPC实现

img_5de75a185a283e10232b7ad72baab75d.png
RPC架构图

Android的RPC主要包含Client、Server和ServiceManager。android中使用ServiceManager来管理所有的所有的Server。ServiceManger启动后首先告诉Binder驱动,将自己标识为ServiceManager。在创建一个Server后,首先通过addService将自己交给ServiceMager管理,Client在需要调用Server时直接通过getService到ServiceManager中查找对应的Server,然后调用Server的方法。

下图给出binder在android中的整体架构,从framework到native再到kernel:

img_5ab31809f97999361686995411b41178.png
Binder整体架构


图中红色部分代表整个framework层binder架构的相关组件,Binder类代码Server端,BinderProxy代表客户端。蓝色代码Native层的Binder架构组件。上层framewoek的binder逻辑建立在native层架构的基础之上,核心逻辑都是交给native处理的。Framework的ServiceManager与native的ServiceManager并不完全对应,framework层的ServiceManager类的实现最终是通过BinderProcy传递给native层来完成的。

Server启动后会开启一个线程不停的读取Binder驱动的读接口,这是一个阻塞调用;在需要响应客户端的时候,会调用Binder驱动的写接口进行数据返回。

Client启动后会不停读取Binder驱动的读接口并阻塞;在调用Service时会开启线程调用Binder的写接口;服务器端处理完后调用写接口、唤醒阻塞中的客户端。

所有的通信都是通过底层的Binder驱动实现的。

3、RPC机制java层代码分析

img_f07f84dbf152ee95cedbceabe8045dc4.png
类图


一般我们使用如下方式来获取系统的Service,例如AlarmManager:

AlarmManager wm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);该代码的运行时序如下所示:

img_650b9c6f3ce88ed796e87d05724ec155.png
getSystemService时序

客户端通过Context.getSystemService获取远程服务时,会转到ContextImpl中调用,ContextImpl有一个ServiceFetcher内部类,通过名字知道该类用于获取Service;ContextImpl里面有个static的WALLPAPER_FETCHER,在APK启动时会加载里面的函数,如下所示,其中registerService会将每个Service对应的构造器ServiceFetcher放入SYSTEM_SERVICE_MAP中。

img_7b4460a8643292cd891bd57740aa84a7.png
创建ServiceFetcher

在调用ContextImpl.getSystemService()时,会调用SYSTEM_SERVICE_MAP对应ServiceFetcher的getService()方法,如下所示。ContextImpl有个全局mServiceCache用于缓存用户创建的Service缓存,这样用户再次获取的时候可以直接从缓存取出,避免再次创建。

img_00949662e356ac0642909a6df5ba69ce.png
SeviceFetcher.getService

如果mServiceCache没有需要的Service缓存,则调用ServiceFetcher的createService进行创建,这里就开始和ServiceManager打交道了,以AlarmManager为例,首先调用ServiceManager.getService()获取IBinder,然后调用IAlarmManager.stub.asInterface将该binder转化成客户端可以直接调用的接口,最后将该接口封装成AlarmManager给客户端使用。

img_4f595c34fe17ef95fd61a66c85037a94.png
registerService

我们看到这里调用了ServiceManagerNative.asInterface获取应IServiceManager实例,传入了BinderInternal.getContextObject(),如下所示:

img_66cbb83c8f24c8cb810d447706129b55.png
BinderInternal.getContextObject

getContextObject方法是一个JNI方法,其实sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());就相当于:sServiceManager = ServiceManagerNative.asInterface(new BinderProxy());

接下来就是调用ServiceManagerNative的asInterface函数了.

img_d67e9ad27c7b48dcb3bf9427d722aa2d.png
ServiceManagerNative.asInterface()

这里的参数obj是一个BinderProxy对象,ServiceManagerProxy提供了addService、getService的实现,也就是ServiceManager最终关联到了ServiceManagerProxy上。到这里,在java层我们已经拥有了ServiceManager的远程接口ServiceManagerProxy,对ServiceManager的所有操作将转接到ServiceManagerProxy中。

如此就实现了对android系统的ServiceManager的RPC调用。那么android系统中提供的那些Service是怎样添加到ServiceManager中去的呢?答案就在SystemServer.java类中,SystemServer伴随系统一起启动,之后会运行ServerThread线程。

img_00b6cd3ecd957400e40457318b47fdd0.png
SystemServer.init2()

ServerThread的run方法会完成所有系统Service的创建,并添加到ServiceManager中去,如下所示:

img_d07f9cb87137d97766bd432937492666.png
添加所有的系统Service

其中addService也是调用的ServiceManagerProxy的addService,这样在系统启动后,相当于在OS层维护了一群系统Service的list。

4、几个概念

IBinder是一个接口,它代表了一种跨进程传输的能力;只要实现了这个接口,就能将这个对象进行跨进程传递;这是驱动底层支持的;在跨进程数据流经驱动的时候,驱动会识别IBinder类型的数据,从而自动完成不同进程Binder本地对象(Server端)以及Binder代理对象(Client获取的Proxy)的转换。

IInterface代表的就是远程server对象具有什么能力, 表示client与server端的调用契约。具体来说,就是aidl里面的接口。

Java层的Binder类,代表的其实就是Binder本地对象。BinderProxy类是Binder类的一个内部类,它代表远程进程的Binder对象的本地代理;这两个类都继承自IBinder,因而都具有跨进程传输的能力;实际上,在跨越进程的时候,Binder驱动会自动完成这两个对象的转换。

在使用AIDL的时候,编译工具会给我们生成一个Stub的静态内部类;这个类继承了Binder,说明它是一个Binder本地对象,它实现了IInterface接口,表明它具有远程Server承诺给Client的能力;Stub是一个抽象类,具体的IInterface的相关实现需要我们手动完成,这里使用了策略模式。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【Android 逆向】Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | 使用 Makefile 构建 Android 平台 NDK 应用 )(二)
【Android 逆向】Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | 使用 Makefile 构建 Android 平台 NDK 应用 )(二)
47 0
【Android 逆向】Android 进程注入工具开发 ( SO 进程注入环境及 root 权限获取 | 进程注入时序分析 )
【Android 逆向】Android 进程注入工具开发 ( SO 进程注入环境及 root 权限获取 | 进程注入时序分析 )
170 0
【Android 逆向】Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | 使用 Makefile 构建 Android 平台 NDK 应用 )(一)
【Android 逆向】Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | 使用 Makefile 构建 Android 平台 NDK 应用 )(一)
51 0
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
59 0
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 一 | mmap 函数简介 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 一 | mmap 函数简介 )
78 0
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 远程 目标进程 中的 /system/lib/libc.so 动态库中的 mmap 函数地址 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 远程 目标进程 中的 /system/lib/libc.so 动态库中的 mmap 函数地址 )
61 0
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )
62 0
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )
45 0
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 调试进程 ATTACH 附着目标进程 | 读取目标函数寄存器值并存档 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 调试进程 ATTACH 附着目标进程 | 读取目标函数寄存器值并存档 )
74 0
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
57 0
+关注
jasmine_ben
2013年毕业于后一直从事android相关的开发。熟悉framework和app开发的相关知识,业余时间喜欢做些开源(https://github.com/JasmineBen)和写一些文章(https://www.jianshu.com/u/45db8e5d0d30)
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Android开发之多进程架构
立即下载
Android插件化:从入门到放弃
立即下载
Android应用启动速度和内存优化实践
立即下载