AIDL相关

一、AIDL oneway 以及in、out、inout参数的理解

https://blog.csdn.net/anlian523/article/details/98476033

oneway

oneway可以用来修饰在interface之前,这样会造成interface内所有的方法都隐式地带上oneway;
oneway也可以修饰在interface里的各个方法之前。
被oneway修饰了的方法不可以有返回值,也不可以有带out或inout的参数。

用 oneway 修饰的 AIDL 接口方法,是单向调用,不需要等待另一个进程的返回结果,所以方法的返回类型也只允许是 void.

oneway 主要有两个特性:异步调用和串行化处理。异步调用是指应用向 binder 驱动发送数据后不需要挂起线程等待 binder 驱动的回复,而是直接结束。像一些系统服务调用应用进程的时候就会使用 oneway,比如 AMS 调用应用进程启动 Activity,这样就算应用进程中做了耗时的任务,也不会阻塞系统服务的运行。

串行化处理是指对于一个服务端的 AIDL 接口而言,所有的 oneway 方法不会同时执行,binder 驱动会将他们串行化处理,排队一个一个调用。

https://juejin.cn/post/6844904147947356173

带oneway的实现

带oneway的方法,不会生成局部变量_reply

不带oneway的实现

不带oneway的方法,会生成局部变量_reply,但当方法返回值为void时,不会生成局部变量_result,这个才是真正的返回值。

in、out、inout参数

  • in参数使得实参顺利传到服务方,但服务方对实参的任何改变,不会反应回调用方。
  • out参数使得实参不会真正传到服务方,只是传一个实参的初始值过去(这里实参只是作为返回值来使用的,这样除了return那里的返回值,还可以返回另外的东西),但服务方对实参的任何改变,在调用结束后会反应回调用方。
  • inout参数则是上面二者的结合,实参会顺利传到服务方,且服务方对实参的任何改变,在调用结束后会反应回调用方。
  • 其实inout,都是相对于服务方。in参数使得实参传到了服务方,所以是in进入了服务方;out参数使得实参在调用结束后从服务方传回给调用方,所以是out从服务方出来。
     

二、binder leak

binder leak就是binder内存泄漏,用于binder通信的buffer大概有4M左右(据同事描述,还没拷证具体数值),在binder通信中如果传输中使用的parcel没有有效release,会造成buffer空间越来越少,然后积累到一定程度,就会出现binder传输的消息在另外一端无法接收。

在进程使用binder driver的时候,最大在kernel空间中开启的虚拟内存空间是4M。一般如果使用IPCThread的API去操作binder的时候是会自动往driver发送FREE_BUFFER的指令做释放操作,所以一般很难出现Binder leak的现象。除非是自己对binder去做IOctl。

三、binder线程耗尽

binder线程到达上限。这个的情景就是app向service发起请求的频率过高,service端如果对所有的业务执行都加了锁的话,则会导致service端用于接收处理binder事件的线程全部卡住,当线程池(default 16个线程)耗尽之后,就无法再处理请求。如果这个时候app的主线程如果再调用该serivce提供的方法,就很容易出现anr。

为解决这种线程池耗尽的问题,应该从app端去限制请求的频率,设定一定的时间间隔才能保证功能正常。 

binder线程池被占满系统对每个process最多分配15个binder线程,这个是谷歌的设计(/frameworks/native/libs/binder/ProcessState.cpp)如果另一个process发送太多重复binder请求,那么就会导致接收端binder线程被占满,从而处理不了其它的binder请求

这时候请求端发起的请求就会阻塞等待了(未设置异步请求的前提下),这本身就是系统的一个限制,如果应用未按照系统的要求来实现对应逻辑,那么就会造成问题。而系统端是不会(也不建议)通过修改系统行为来兼容应用逻辑,否则更容易造成其它根据系统需求正常编写的应用反而出现不可预料的问题。

判断Binder是否用完,可以在trace中搜索关键字"binder_f",如果搜索到则表示已经用完,然后就要找log其他地方看是谁一直在消耗binder或者是有死锁发生

anr解决常见问题:https://juejin.cn/post/6844903903868223502

问题排查方法

这个目录下的文件,/sys/kernel/debug/binder,来查看所有进程的使用binder的状况来确定是上述两种状况的哪一种,主要是cat transactions这个文件来查看运行状况

proc代表进程号;

一行buffer代表有一个binder通信在占用buffer的空间(具体其他打印的意义需要参考binder driver);

thread开头的打印,这个代表的是进程具有的接收binder的线程

如果针对第一种binder leak的情况,在程序运行过程中该proc下的buffer的行数会越来越多,不停地增长,这样基本上你就能判断是binder leak的情况。

另外一种以thread开头的打印,这个代表的是进程具有的接收binder的线程,如果这类行数超多,16个,基本就可以确定是binder线程池已经满了。

https://zhuanlan.zhihu.com/p/22645229

猜你喜欢

转载自blog.csdn.net/cpcpcp123/article/details/115122839