苏州网站搜索优化,景德镇做网站,网页视频怎么下载ios,网站的用户注册怎么做Binder是IPC#xff08;进程间通信#xff09;的一种机制#xff0c;它允许不同的应用或系统服务在不同的进程中安全地交换数据。Binder的核心原理是基于客户端-服务器模型#xff08;C/S架构)。 一、Binder的定义
1. Binder是Android中的一个类#xff0c;它继承了IBind…Binder是IPC进程间通信的一种机制它允许不同的应用或系统服务在不同的进程中安全地交换数据。Binder的核心原理是基于客户端-服务器模型C/S架构)。 一、Binder的定义
1. Binder是Android中的一个类它继承了IBinder接口。
2. 从IPC角度来说Binder是Android中的一种跨进程通信方式Binder还可以理解为一种虚拟的物理设备它的设备驱动是/dev/binder该通信方式在linux中没有
3. 从Android Framework角度来说Binder是ServiceManager连接各种ManagerActivityManager、WindowManageretc和相应ManagerService的桥梁
4. 从Android应用层来说Binder是客户端和服务端进行通信的媒介当你bindService的时候服务端会返回一个包含了服务端业务调用的Binder对象通过这个Binder对象客户端就可以获取服务端提供的服务或者数据这里的服务包括普通服务和基于AIDL的服务。
一、Binder架构
在Android系统中Binder架构主要由以下几个部分组成
1.Binder驱动程序这是Linux内核的一部分负责处理跨进程通信的所有底层细节。
2.ServiceManager这是一个特殊的系统服务负责管理所有通过Binder进行通信的服务。它维护一个服务列表允许其他服务注册和查询服务。
3.Server端这是提供某种服务的组件比如系统服务或应用服务。
4.Client端需要使用Server端提供服务的组件。 二、Binder的工作流程
1、Client和Server都使用同一个AIDL文件包名相同编译后两边都会生成IMyService.java,其中有Stub实体和Proxy代理两个对象
2、Server端通过AndroidManifest.xml 注册Service
3、Client通过bindService()获得服务的代理Stub.Proxy()
4、Client 调用AIDL的方法add()其实调用的是IMyService.java中的Stub.Proxy.add(),最终通过BinderProxy.java的transact()向服务端发送
5、过Binder驱动的流程进入到服务端的onTransact()根据Client发送的TRANSACTION code解析进入相应的流程处理进入add()
6、MyService在被绑定时有了实体IMyService.Stub最终进入MyService.java的add()处理完成接口调用调用完成后把数据写入Parcel通过reply发送给Client 四、Binder通信原理
1. Binder是基于内存映射mmap设计实现的通过这种方式直接操作映射的这一部分内存通过mmapBinder通信时只需要经历一次数据复制从而获得更好的性能。
2. Binder通信过程
. 首先Binder驱动在内核空间中开辟出一个数据接收缓冲区。 . 接着在内核空间中开辟出一个内核缓冲区。 . 将内核缓冲区与数据接收缓冲区建立映射关系。 . 将数据接收缓冲区与接收进程的用户空间地址建立映射关系。 . 发送方进程通过copy_from_user将数据从用户空间复制到内核缓冲区。 . 由于内核缓冲区与数据接收缓冲区有映射关系同时数据接收缓冲区与接收进程的用户空间地址有映射关系所以在接收进程中可以直接获取到这段数据。 五、参数定义
Stub类Binder的实现类服务端通过这个类来提供服务。
Proxy类服务器的本地代理Binder客户端通过这个类调用服务器的方法。
asInterface()客户端调用将服务端的返回的Binder对象转换成客户端所需要的AIDL接口类型对象。返回对象
1.若客户端和服务端位于同一进程则直接返回Stub对象本身
2.否则返回的是系统封装后的Stub.proxy对象。
asBinder()根据当前调用情况返回代理Proxy的Binder对象。
onTransact()运行服务端的Binder线程池中当客户端发起跨进程请求时远程请求会通过系统底层封装后交由此方法来处理。
transact()运行在客户端当客户端发起远程请求的同时将当前线程挂起。之后调用服务端的onTransact()直到远程请求返回当前线程才继续执行。
Parcel这是一种用于封装数据的数据结构可以在进程间传输。它类似于Java中的序列化对象但更轻量级且效率更高。
isBinderAlive()用于检查一个Binder对象是否仍然存活
linkToDeath注册对Binder死亡通知的观察者在其死亡后会收到相应的通知 六、进程通信对比
1. 共享内存
定义共享内存是进程间通信中最简单的方式之一共享内存允许两个或更多进程访问同一块内存当一个进程改变了这块地址中的内容的时候其它进程都会察觉到这个更改。
性能和安全分析因为共享内存是访问同一块内存所以数据不需要进行任何复制是IPC几种方式中最快性能最好的方式。由于能任意的访问和修改内存中的数据如果有恶意程序去针对某个程序设计代码很可能导致隐私泄漏或者程序崩溃所以安全性较差。
2. 管道
定义它具有固定的读端和写端写进程通过写段向管道文件里写入数据读进程通过读段从读进程中读出数据构成一条数据传递的流水线。
性能和安全分析
管道一次通信需要经历2次数据复制进程A - 管道文件管道文件 - 进程B。管道的读写分阻塞和非阻塞管道创建会分配一个缓冲区而这个缓冲区是有限的如果传输的数据大小超过缓冲区上限或者在阻塞模式下没有安排好数据的读写会出现阻塞的情况。
3. 消息队列
定义消息队列是存放在内核中的消息链表每个消息队列由消息队列标识符表示。消息队列允许多个进程同时读写消息发送方与接收方要约定好消息体的数据类型与大小。
性能和安全分析消息队列克服了信号承载信息量少、管道只能承载无格式字节流等缺点消息队列一次通信同样需要经历2次数据复制进程A - 消息队列消息队列 - 进程B。
4. Socket
定义Socket原本是为了网络设计的但也可以通过本地回环地址 (127.0.0.1) 进行进程间通信。Socket是一种通信机制位于应用层和传输层之间提供了一组接口用于应用程序之间的通信。
性能和安全分析一个Socket会拥有两个缓冲区一读一写由于发送/接收消息需要将一个Socket缓冲区中的内容拷贝至另一个Socket缓冲区所以Socket一次通信也是需要经历2次数据复制。
5.Binder优势
1. 性能优势
. 在移动设备上性能受限制的设备比如要省电广泛地使用跨进程通信对通信机制的性能有严格的要求Binder相对出传统的Socket方式更加高效。
. Binder数据拷贝只需要一次而管道、消息队列、Socket都需要2次共享内存方式一次内存拷贝都不需要但实现方式又比较复杂。
2. 安全优势
. 传统的进程通信方式对于通信双方的身份并没有做出严格的验证比如Socket通信ip地址是客户端手动填入很容易进行伪造。 . 而Binder机制从协议本身就支持对通信双方做身份校检因而大大提升了安全性。 . 还有一些好处如实现面象对象的调用方式在使用Binder时就和调用一个本地实例一样。 Binder 共享内存 Socket 性能 数据拷贝一次 无需拷贝 数据拷贝两次 稳定 C/S架构清晰明朗。Client与Server相对独立稳定性好 实现与控制复杂需要自行处理并同步等问题。 基于C/S架构 安全性 内核添加身份标识可靠 依赖上层协议访问接入点开放不安全 依赖上层协议访问接入点开放不安全
七、代码分析
/** This file is auto-generated. DO NOT MODIFY.*/
package com.flyme.auto.account.manager;
public interface IAccountManagerInterface extends android.os.IInterface
{/** Default implementation for IAccountManagerInterface. */public static class Default implements com.flyme.auto.account.manager.IAccountManagerInterface{/*** 获取当前登录的账号数据*/Override public java.lang.String getAccountInfo() throws android.os.RemoteException{return null;}/*** 判断当前是否已登录*/Override public boolean isLoggedIn() throws android.os.RemoteException{return false;}Overridepublic android.os.IBinder asBinder() {return null;}}/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.flyme.auto.account.manager.IAccountManagerInterface{private static final java.lang.String DESCRIPTOR com.flyme.auto.account.manager.IAccountManagerInterface;/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an com.flyme.auto.account.manager.IAccountManagerInterface interface,* generating a proxy if needed.*///asInterface是Android Binder IPC机制中用于将Binder对象转换为特定接口的关键方法// 它使得客户端能够调用服务端提供的方法和服务实现进程间的通信和数据交换public static com.flyme.auto.account.manager.IAccountManagerInterface asInterface(android.os.IBinder obj){if ((objnull)) {return null;}android.os.IInterface iin obj.queryLocalInterface(DESCRIPTOR);if (((iin!null)(iin instanceof com.flyme.auto.account.manager.IAccountManagerInterface))) {return ((com.flyme.auto.account.manager.IAccountManagerInterface)iin);}return new com.flyme.auto.account.manager.IAccountManagerInterface.Stub.Proxy(obj);}//Android Binder IPC机制中用于获取接口对象所关联的IBinder实例的方法它提供了直接操作IBinder对象的能力但需要谨慎使用Override public android.os.IBinder asBinder(){return this;}//Android Binder IPC机制中服务端用于处理客户端请求的关键方法Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{java.lang.String descriptor DESCRIPTOR;switch (code){case INTERFACE_TRANSACTION:{reply.writeString(descriptor);return true;}case TRANSACTION_getAccountInfo:{data.enforceInterface(descriptor);java.lang.String _result this.getAccountInfo();reply.writeNoException();reply.writeString(_result);return true;}case TRANSACTION_isLoggedIn:{// Android Binder IPC 机制中用于确保接口一致性和安全性的一个方法data.enforceInterface(descriptor);boolean _result this.isLoggedIn();reply.writeNoException();reply.writeInt(((_result)?(1):(0)));return true;}default:{return super.onTransact(code, data, reply, flags);}}}//Proxy的实现通常依赖于具体的接口定义和服务端实现。在Android中可以使用AIDL来定义接口并自动生成Proxy和Stub存根代码。// Stub是服务端的一个组件它与Proxy相对应负责接收和处理来自客户端的请求private static class Proxy implements com.flyme.auto.account.manager.IAccountManagerInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote remote;}Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}/*** 获取当前登录的账号数据*/Override public java.lang.String getAccountInfo() throws android.os.RemoteException{android.os.Parcel _data android.os.Parcel.obtain();android.os.Parcel _reply android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);boolean _status mRemote.transact(Stub.TRANSACTION_getAccountInfo, _data, _reply, 0);if (!_status getDefaultImpl() ! null) {return getDefaultImpl().getAccountInfo();}_reply.readException();_result _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}/*** 判断当前是否已登录*/Override public boolean isLoggedIn() throws android.os.RemoteException{android.os.Parcel _data android.os.Parcel.obtain();android.os.Parcel _reply android.os.Parcel.obtain();boolean _result;try {//writeInterfaceToken方法的使用有助于确保客户端和服务端之间的接口一致性// 并减少因接口不匹配而导致的通信错误或安全问题。它是Android Binder IPC机制中保证通信正确性和安全性的一个重要环节_data.writeInterfaceToken(DESCRIPTOR);boolean _status mRemote.transact(Stub.TRANSACTION_isLoggedIn, _data, _reply, 0);if (!_status getDefaultImpl() ! null) {return getDefaultImpl().isLoggedIn();}_reply.readException();_result (0!_reply.readInt());}finally {_reply.recycle();_data.recycle();}return _result;}public static com.flyme.auto.account.manager.IAccountManagerInterface sDefaultImpl;}static final int TRANSACTION_getAccountInfo (android.os.IBinder.FIRST_CALL_TRANSACTION 0);static final int TRANSACTION_isLoggedIn (android.os.IBinder.FIRST_CALL_TRANSACTION 1);public static boolean setDefaultImpl(com.flyme.auto.account.manager.IAccountManagerInterface impl) {// Only one user of this interface can use this function// at a time. This is a heuristic to detect if two different// users in the same process use this function.if (Stub.Proxy.sDefaultImpl ! null) {throw new IllegalStateException(setDefaultImpl() called twice);}if (impl ! null) {Stub.Proxy.sDefaultImpl impl;return true;}return false;}public static com.flyme.auto.account.manager.IAccountManagerInterface getDefaultImpl() {return Stub.Proxy.sDefaultImpl;}}public java.lang.String getAccountInfo() throws android.os.RemoteException;public boolean isLoggedIn() throws android.os.RemoteException;}