0、Binder是什么?
1)机制:是一种进程间通信机制;
2)驱动:是一个虚拟物理设备驱动:
3)应用层:是一个能发起通信的Java类;service -> new stub(继承自Binder)
1、Binder有什么优势?
多进程的使用及优势:虚拟机分配给各个进程的运行内存是有限制的,LMK也会优先回收对系统资源的占用多的进程。
1)突破进程内存限制,如图库占用内存过多;
2)功能稳定性:独立的通信进程包保持长连接稳定性;
3)规避系统内存泄露:独立的WebView进程阻隔内存泄漏导致的问题;
4)隔离风险:对于不稳定的功能放入独立进程,避免导致主进程崩溃;
进程间的通信机制:共享内存、socket、管道、消息队列
特点:
1)性能:需要拷贝一次:
2)特点:基于C/S(客户端/服务端)架构:
3)安全性:为每个APP分配UID同时支持实名和匿名,而共享内存依赖于上层协议
uid可以找到对应的service、防止恶意软件入侵手机。再service注册时 将uid传给binder
实名:注册的;匿名:
2、Binder是怎么做到一次拷贝(系统调用)的?
传统的ipc通信,线程之间的内存是可以共享的 但进程是内存隔离的
进程之间只能通过内核控件调用
内存映射-》
虚拟内存-》安卓开发所说的内存-》指针-》虚拟地址(一个虚拟的地址指向)
物理内存-》
所有进程的内核空间是共享一个物理内存的(地球仪和地球的关系)
用户空间和内核控件通过系统调用,而Binder相当于给用户空间和内核控件提供了一个共享区域进行内存映射 因此无需两次copy
Binder又google工程师处理数据 无需担心数据死锁
3、MMAP的原理讲解
memory mapping
把虚拟内存和指定的物理内存进行绑定,开辟一块空间 指向该虚拟内存 将内存指向指针
虚拟内存-》物理内存(Binder驱动(文件)提供)
4、Binder机制是如何跨进程的
startActivity会发生几次通信?==bind Service会发生几次跨进程通信?进行6次跨进程通信。
init pid=1 -> init.rc-》zygote-》fork system service
serviceManager(服务器表)-》见通信机制
5、描述AIDL生产的java类细节
public interface IBookManager extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.xushuzhan.aidltest.IBookManager {
private static final java.lang.String DESCRIPTOR = "com.example.xushuzhan.aidltest.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.xushuzhan.aidltest.IBookManager interface,
* generating a proxy if needed.
*/
public static com.example.xushuzhan.aidltest.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.xushuzhan.aidltest.IBookManager))) {
return ((com.example.xushuzhan.aidltest.IBookManager) iin);
}
return new com.example.xushuzhan.aidltest.IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_basicTypes: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0 != data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_getBook: {
data.enforceInterface(DESCRIPTOR);
com.example.xushuzhan.aidltest.BookBean _result = this.getBook();
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.example.xushuzhan.aidltest.BookBean _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.xushuzhan.aidltest.BookBean.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.xushuzhan.aidltest.IBookManager {
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;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean) ? (1) : (0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public com.example.xushuzhan.aidltest.BookBean getBook() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.example.xushuzhan.aidltest.BookBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBook, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = com.example.xushuzhan.aidltest.BookBean.CREATOR.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(com.example.xushuzhan.aidltest.BookBean book) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
//定义返回书本的方法
public com.example.xushuzhan.aidltest.BookBean getBook() throws android.os.RemoteException;
//定义添加书本的方法,这里的 in 代表数据的流向是:客户端->服务端,服务端对数据的任何修改都不会影响到客户端
public void addBook(com.example.xushuzhan.aidltest.BookBean book) throws android.os.RemoteException;
}
**onTransact(int code, Parcel data, Parcel reply, int flags):**这就是一个比较核心的方法了,它主要是用来执行远程调用的目标方法,执行完后把返回值写入reply中。这个方法是运行在服务端的Binder线程池中,客户端发起请求的时候,会通过系统底层封装后交给此方法来处理,如果返回false,那么客户端将请求失败(调用不到所请求的方法)。参数如下:
**code:**即AIDL接口中方法的唯一标识,通过它可以确定调用的是那个方法。
**data:**客户端远程调用方法的时候传过来的参数的值被封装进了这个data,需要就可以取出。
**reply:**当前方法的返回值会被封装进reply。
**flags:**只有0和1(FLAG_ONEWAY)两种取值,取0表示同步操作(默认),取1表示客户端单向操作,无需等待服务端响应。
6、四大组件底层通信机制
参考aidl和binder通信原理
7、为什么Intent不能传递大数据?==binder传递数据限制
同步传输最大限制1M-8k约等于512k 异步要除以2。binder mmap底层异步有底层的限制