Binder 机制 javanative

news2024/9/24 3:22:57

         

一:Binder介绍

Binder是一套ipc通信方案

Binder框架定义了四个角色: Server ,Client,ServiceManager (以后简称SMgr)以及Binder驱动。其中Server ,Client,SMgr运行于用户空间,驱动运行于内核空间。这四个角色的关系和互联网类似: Server是服务器, Client是客户终端, SMgr是域名服务器(DNS),驱动是路由器。 在网络通信中域名服务器的地址是一个固定的地址,所以很方便的通过这个固定地址拿到。那么在Binder中, SMgr 是一个进程, Server是另一个进程, Server向SMgr注册Binder必然会涉及进程间通信。当前实现的是进程间通信却 又要用到进程间通信,这就好象蛋可以孵出鸡前提却是要找只鸡来孵蛋。 Binder的实现比较巧妙:预先创造一只鸡来 孵蛋: SMgr和其它进程同样采用Binder通信, SMgr是Server端,有自己的Binder对象(实体),其它进程都是 Client,需要通过这个Binder的引用来实现Binder的注册,查询和获取。 SMgr提供的Binder比较特殊,它没有名字 也不需要注册,当一个进程使用BINDER_SET_CONTEXT_MGR命令将自己注册成SMgr时Binder驱动会自动为它创建 Binder实体(这就是那只预先造好的鸡)。其次这个Binder的引用在所有Client中都固定为0而无须通过其它手段获得。也就是说, 一个Server若要向SMgr注册自己Binder就必需通过0这个引用号和SMgr的Binder通信。类比网络通信, 0号引用就好比域名服务器的地址,你必须预先手工或动态配置好。要注意这里说的Client是相对SMgr而言的,一个应用程序可能是个提供服务的Server,但对SMgr来说它仍然是个Client。

BInder通信的流程梳理:

1. 首先, 一个进程使用 BINDERSETCONTEXT_MGR 命令通过 Binder 驱动将自己注册成为 ServiceManager;

2. Server 通过驱动向 ServiceManager 中注册 Binder( Server 中的 Binder 实体),表明可以对外提供服务。驱动为这个 Binder 创建位于内核中的实体节点以及 ServiceManager 对实体的引用,将名字以及新建的引用打包传给 ServiceManager ,ServiceManger 将其填入查找表。

3. Client 通过名字,在 Binder 驱动的帮助下从 ServiceManager 中获取到对 Binder 实体的引用。

4. 通过这个Binder实体引用, Client实现和 Server 进程的通信。

二:Binder的创建

总的来说, Binder的初始化是在进程已创建就完成了。创建进程后会第一时间为这个进程打开一个binder驱 动,并调用mmap接口向Binder驱动中申请内核空间的内存。

三:AIDL原理

.aidl文件

-----------------------

interface IServer {

int testFunction(String s);

}

远程服务

----------------------

public class RemoteTestService extends Service {

private IServer.Stub serverBinder = new IServer.Stub() {

@Override public int testFunction(String s) throws RemoteException {

Log.i("test","testFunction s= " + s);

return 0;

}

};

@Nullable @Override

public IBinder onBind(Intent intent) {

return serverBinder;

}

}

客户端

------------

public class MainActivity extends AppCompatActivity {

private IServer iServer;

private ServiceConnection serviceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

iServer = IServer.Stub.asInterface(service);

System.out.println("onServiceConnected");

try {

int a = iServer.testFunction("test string");

Log.i("test", "after testFunction a:" + a);

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public void onServiceDisconnected(ComponentName name) {

Log.i("test", "onServiceDisconnected");

}

};

@Override

protected void onCreate( Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Intent intent = new Intent(MainActivity.this, RemoteTestService.class);

bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

}

}

------------------------------------

aidl文件自动生成的Java文件如下:

通过aidl文件生成了Java文件,这个类的静态内部类Stub(继承了 Binder,实现了接口方法),主要逻辑在方法asInterface,如下图

asInterface方法之后也就能调用服务端端方法了,testFunction()方法进行数据的传递,有同步和异步之分。aidl接口中定义的方法都是在实现BInder的线程池中执行。详见 :aidl中的oneWay的语法解释

客户端:持有proxy

服务端:持有stub

stub是类IServer的静态内部类,proxy是stub的静态内部类通过构造方法持有stub引用

服务端和客户端同一进程:客户端可以直接使用stub类

服务端和客户端非同一进程:客户端需要获取接口类型的stub也就是Proxy,而Proxy持有stub,这个接口就是aidl

aidl通信的基本步骤如下:

1. Client通过ServiceConnection获取到Server的Binder,并且封装成一个Proxy。

2. 通过Proxy来同步调用IPC方法(

testFunction),同时通过Parcel将参数传给Binder,最终触发Binder的

transact方法。

3. Binder的transact方法最终会触发到Server上Stub的onTransact方法。

4. Server上Stub的onTransact方法中,会先从Parcel中解析中参数,然后将参数带入真正的方法中执行,然后将

结果写入Parcel后传回。

5. 请注意: Client的Ipc方法中,执行Binder的transact时,是阻塞等待的, 一直到Server逻辑执行结束后才会继

续执行。当然,如果IPC方法是oneWay的方式,那么就是非阻塞的等待。

6. 当Server返回结果后, Client从Parcel中取出返回值,于是实现了一次IPC调用。

所以, aidl 文件会生成一个java文件,这个java文件的意义在于将核心的binder驱动封装成为java层可以直接调用的

代码,同时也处理了将java层的数据格式转换为Parcel格式数据进行跨进程传递的一个功能。所以, aidl是一个使用binder的标准方案,该方案的代码同样的可以通过用户自己编写的方式完成

四:BindService的原理

1,client(客户端进程)

2,service (远端服务进程)

3,ams(systemservicer进程)

4,serviceManager(进程)

具体流程如下:

1)Activity作为Client发起bindService,最终会调度到AMS 去执行bindService。在这个过程中, Client要去调用

AMS的代码,所以此时就会涉及到跨进程调度,基于第三章的Binder通信模型我们不难知道, Client会先和

ServiceManager通信,从ServiceManager中拿到AMS的IBinder。

2)Activity拿到AMS的IBinder后,跨进程执行AMS的BindService函数;

3)由于AMS管理所有的应用进程,因此AMS中持有了应用进程的Binder,所以此时AMS可以发起第4步也就是跨进

程调度scheduleBindService();

4)Server端会在收到AMS的bindService的请求后,会将自己的IBinder发送给client,但是Server必须通过AMS才能

将Binder对象传过去,所以此时需要跨进程从ServiceManager中去拿到AMS的binder;

5)Server端通过AMS的binder直接调用AMS的代码publishService(),将service的Binder发送给AMS;

6)经过层层调用,最终AMS讲Server端的binder通过回调connect函数传递给了Client端的Activity;

以上就是bindService的全流程,这个流程主要的目的是将Server端的Binder对象发送给Client端。从此以后, Client端就可以通过Server端的binder与Server端像调用自己的代码一样完成跨进程通信了。

五:Binder的优点

高效:数据拷贝一次,通过mmap(内存映射)提高数据传递效率

内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间反之内核空间对这段区域的修改也能直接反应到用户空间

安全:内核添加身份识别

稳定:c/s架构

六:Java& Native层面 Binder相互转化

因此我们必须研究一下Java framework层与Native层之间的相互调动。

1)Client端通过ServiceManager 拿到Server端服务的Binder 代理,也就是BinderProxy(是Server端Binder的一个 代理);

2)这个BinderProxy的访问需要经过JNI层的Android_util_binder类将请求转交给native的BpBinder(p代表代理的意思);

3) BpBinder会通过ioctl将请求转交给Binder驱动设备;

4)在服务端注册了一个监听请求的回调函数, 一旦驱动层收到BpBinder 的调用,就会回调BBInder注册的回调函 数,于是,就将请求转给了BBinder;

5) BBinder拿到请求后,会进行一些数据的处理,然后通过JNI将请求转交给了java类;

6)java层会通过aidl中的函数将请求发送给Server端的实现者,由Server端通过stub 去调用相关的执行代码,并将 结果通过类似的路径返回。

以上只是一个大概的流程

七: ServiceManager解析

ServiceManager作为一个起始的服务,是通过init.rc 来启动的。

//system\core\rootdir\init.rc

//启动的服务 ,这里是用的服务名称。服务名称是在对应的rc文件中注册并启动的

start servicemanager

具体的服务信息是在servicemanger.rc命名并定义的

//\frameworks\native\cmds\servicemanager\servicemanager.rc

service servicemanager / system/ bin/ servicemanager

class core animation

user system

//说明以用户system身份运行

group system readproc

//说明servicemanager是系统中的关键服务,

//关键服务是不会退出的 ,如果退出了 ,系统就会重启 ,当系统重启时就会启动用onrestart关键字修饰的进程,

//比如zygote、media、 surfaceflinger等等。

critical

onrestart restart healthd

onrestart restart zygote

onrestart restart audioserver

onrestart restart media

onrestart restart surfaceflinger

onrestart restart inputflinger

onrestart restart drm

onrestart restart cameraserver

onrestart restart keystore

onrestart restart gatekeeperd

onrestart

. .

restart thermalservice

八:ServiceManager的客户端 Binder 的通信

九:ServiceManager的服务端 Binder 的通信

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1380717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SRM供应商招标采购管理系统(源码)

软件相关资料获取:点我获取 一、SRM供应商在线采购 SRM供应商在线采购是指企业通过互联网平台,实现对供应商的在线招募、选择、关系管理等一系列活动。这种采购方式具有高效、透明、便于管理的特点,能够帮助企业降低采购成本,提…

AI副业拆解:「一键解锁」告别熬夜赶PPT,AI大模型带你秒变高效演示达人!

今天,我注意到一条新闻报道,揭示了今年全球及国内科技企业正激烈竞争,纷纷借力大模型技术扩展各自的商业疆界。据统计,截至今年7月尾声,我国已累计推出了130个大模型项目,其中尤为显著的是,仅在…

华为设备VRRP配置

核心代码: 需要对所有虚拟路由器设置(要进入到对应的端口) vrrp vrid 38 virtual-ip 192.168.10.254 vrrp vrid 38 priority 120 vrrp vrid 38 track int g0/0/1 reduced 30①mac由vrid生成 ②指定虚拟ip ③虚拟ip作为内部主机的网关&#x…

软件测试|Python数据可视化神器——pyecharts教程(十)

使用pyecharts绘制漏斗图 简介 漏斗图(Funnel Chart)是一种用于可视化数据流程或转化率的图表类型。它通常由一系列阶段组成,每个阶段都有一个名称和一个值,表示在该阶段的转化量或数据流程的进展情况。漏斗图的名称来源于其外观…

OpenAI ChatGPT-4开发笔记2024-06:最简Embedding

Embedding embedding直译是:嵌入。和实际意思有些差距。其实就是把文本转换为向量表示的过程。用“向量化”更直接,但这又和tensor有点儿混。它是变成向量的一个过程。 embedding 的应用领域: 文本分类: 将文本嵌入转换为向量后…

HCIP-1

一、网络类型: 点到点 BMA:广播型多路访问 – 在一个MA网络中同时存在广播(洪泛)机制 NBMA:非广播型多路访问—在一个MA网络中,没有洪泛机制 MA:多路访问 在一个网段内,存在的节…

SQL Server 配置远程连接

Windows 安装好 SQL Server 的 SSMS,打开SSMS配置远程连接 找到 配置管理器 启用 TCP/IP 打开防火墙设置 新建入站规则 端口TCP - 特定本地端口 (1433)允许连接下一步名称完成 重启 SQL Server 服务

深入理解 Spark(二)SparkApplication 提交和运行源码分析

spark 核心流程 yarn-client yarn-cluster spark 任务调度 spark stage 级别调度 spark task 级别调度 失败重试和白名单 对于运行失败的 Task,TaskSetManager 会记录它失败的次数,如果失败次数还没有超过最大重试次数,那么就把它放回待调…

教育观察期刊投稿邮箱、投稿要求

《教育观察》创刊于2012年,是国家新闻出版总署批准的正规教育类学术期刊,本刊致力于在教育实践中以“观察”为方法,以“观察者”为主体,以“新观察”为旨趣,打造从教育实践中洞察教育未来的教育研究与交流的平台。主要…

软件测试|深入理解Python中的re.search()和re.findall()区别

前言 在Python中,正则表达式是一种强大的工具,用于在文本中查找、匹配和处理模式。re 模块提供了许多函数来处理正则表达式,其中 re.search()和 re.findall() 是常用的两个函数,用于在字符串中查找匹配的模式。本文将深入介绍这两…

【WEB API自动化测试】接口文档与在线测试

这一篇我们主要介绍如何做API帮助文档,给API的调用人员介绍各个 API的功能, 输入参数,输出参数, 以及在线测试 API功能(这个也是方便我们自己开发调试) 我们先来看看我们的API最终帮助文档及在线测试最终达到的效果: 概要图 GET API 添加产品API: 删除…

电影开场后也能退票,“电影仅退款”能治烂片病吗?

1月11日,“#电影开场后也能退票了#”词条登上微博热搜。 根据央视六套《中国电影报道》,从今年元旦开始,湖南长沙部分影院开启了新型电影保险模式的试点。 在电影开场后30分钟以内,市民如果对电影内容不满意,可借助小…

超维空间S2无人机使用说明书——61、ROS无人机4G远程控制

4G模块使用说明 引言:为了实现对无人机的远程控制,我们采用了4G通信的方案,该方案需要硬件以及相关软件的支持。4G通信是可选择功能,请确认无人机型号是否选配了4G通信。 一、4G通信方案 我们的4G通信主要通过两种方式实现&…

软件测试|如何实现字典的键值互换,你会了吗?

简介 在Python中,字典是一种非常有用的数据结构,它将数据存储为键值对,并且键必须是唯一的。有时候,我们可能需要将字典的键和值互换,以便查找或操作数据更加方便。本文将详细介绍如何在Python中实现字典键值的互换操…

Flink(十二)【容错机制】

前言 最近已经放假了,但是一直在忙一个很重要的自己的一个项目,用 JavaFX 和一个大数据组件联合开发一个功能,也算不枉我学了一次 JavaFX,收获很大,JavaFX 它作为一个 GUI 开发语言,本质还是 Java&#xff…

Servlet-体系结构

一、思考 读者阅读完上一篇关于Servlet基本概念的文章后,我们知道每次实现一个Servlet,都需要覆盖五个接口,我们对除service接口外的其它四个接口,我们通常不会做什么处理。那么,这种实现方式是否有些繁琐呢&#xff…

python_selenium_安装基础学习

目录 1.为什么使用selenium 2.安装selenium 2.1Chrome浏览器 2.2驱动 2.3下载selenium 2.4测试连接 3.selenium元素定位 3.1根据id来找到对象 3.2根据标签属性的属性值来获取对象 3.3根据xpath语句来获取对象 3.4根据标签的名字获取对象 3.5使用bs4的语法来获取对象…

数字智慧驱动:数据可视化如何助力大企业效率飙升?

在当今信息大爆炸的时代,大型企业面临着前所未有的数据挑战。数据量庞大、多样化的信息汇聚,无疑成为企业高效运营的挑战之一。幸运的是,数据可视化作为一种强大的工具,正成为大型企业提高效率、优化决策的得力助手。 数据可视化首…

开发代码基础

首先安装驱动,在ARDUINO环境下安装,然后安装开发板,详见哔哩哔哩教程 1:接入点模式(也称 AP) 通过以下示例程序,NodeMCU将会建立一个名为taichi-maker的WiFI。您可以使用手机或电脑连接该WiFi…

力扣2182.构造限制重复的字符串

思路:先记录每个字符的出现次数,构建一个新字符串,从尾取字符,每取一个该字符个数-1,若该字符已经取到有repeatLimit个,则递归取次大的字符,并对应字符个数-1,若没有次大字符了&…