Binder机制原理
1.Binder是什么?
- 机制:Binder是一种进程间通信机制。
- 驱动:Binder是一个虚拟物理设备驱动
- 应用层:Binder是一个能够发起通信的java类
2.多进程的使用以及优势
虚拟机分配给各个进程的运行内存是有限制的,LMK也会优先回收对系统资源占用多的进程
- 突破进程内存限制
- 功能稳定性 ,独立的通信进程保持长连接的稳定性。(极光推送,百度定位)
- 规避系统内存泄漏:独立的WebView进程阻隔内存泄漏导致的问题。
- 隔离风险,对于不稳定的功能放入到独立进程,避免导致主进程的崩溃.
3.Linux中进程间的通信机制有哪些?与传统的IPC机制相比,有哪些优势?
1732615212620.pngBinder 共享内存 socket 管道 消息队列 型号
-
Binder:拷贝一次 基于CS架构,易用性强(Service>>binder >>分配uid 【如果是恶意软件,通过uid找到,很安全】)
-
共享内存: 无需拷贝 控制复杂,易用性差 (多线程使用同一块内存时,可能出现死锁,数据不同步问题,访问接入点事开放的,不安全) mmap原理实现
-
socket : 拷贝二次 基于CS架构,效率低,开销大 (访问接入点是开放的,不安全)
-
管道Pipe: 拷贝二次,数据传输也是单向的,一个进程向管道写入数据,另一个进程从管道读取数据.
image.png
-
消息队列:拷贝二次,消息队列是消息的链表,存放在内核中,每个消息队列都有队列id来标识,独立与发送和接收进程,进程终止时,消息队列中的内容不会被删除,也可以实现随机查询,消息不一定要以先进先出的次序读取,也可以按照消息的类型或者优先级读取.
image.png -
信号 (比如Vsync)是基于事件的异步通知,而不是数据的拷贝,当某个时间发生时,内核会向目标进程发送一个信号,信号会被添加到目标进程的信号队列中,当进程从内核态返回用户态时,内核会检查信号队列,并根据注册的信号处理函数来处理信号.
注意:有些资料说是4次拷贝(发送进程的用户空间>>发送进程内核空间缓冲区>>内存>>用户进程内核缓冲区>>用户进程用户空间),也可以简化为2次拷贝(用户空间 >>内核缓冲区>>用户空间)
4.Binder是如何做到一次拷贝的?
进程1 用户空间 | 内核空间 共享同一块物理内存A【Binder驱动提供】
内存映射 >>> 虚拟内存 ,物理内存 指针就是表示虚拟内存
地球仪 && 地球 关系
进程2 用户空间 | 内核空间 共享同一块物理内存B 【Binder驱动提供】
image.png image.png4.MMAP(Memory Map)内存映射的原理
虚拟内存划分
1732617169964.png内存映射原理
通过mmap函数将文件或物理内存映射到进程的虚拟地址空间,避免了数据拷贝和用户态与内核态的转换,提高了通信速度。
5.Binder通过Java代码是如何实现的呢?
5.1.服务端,客户端BookManager.aidl文件,根据aidl接口,系统自动帮忙生成Stub类继承Binder并实现BookManager接口【服务端和客户端生成的代码是一样的,只是调用逻辑不一样而已】
interface BookManager{
List<Book> getBookList();
}
5.2.根据aidl接口,自动生成BookManager.java类(aidl就是对binder的封装)
//SDK提供
public interface IBinder {
int FIRST_CALL_TRANSACTION = 1;
boolean isBinderAlive();
}
//SDK提供
public class Binder implements IBinder {
public boolean isBinderAlive() {
throw new RuntimeException("Stub!");
}
}
//SDK提供
public interface IInterface {
IBinder asBinder();
}
//系统生成
public interface BookManager extends android.os.IInterface {
public static abstract class Stub extends Binder implements BookManager {
//自动生成的TRANSACTION_getBookList
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
private static final String DESCRIPTOR = "com.lypeer.ipcclient.BookManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
//把IBinder对象转BookManager接口的,如果需要的话,就生成一个Proxy代理类
public static BookManager asInterface(IBinder obj) {
if ((obj == null)) {
return null;
}
//此处得到的iin==null
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);//iin ==null
if (((iin != null) && (iin instanceof BookManager))) {
return ((com.lypeer.ipcclient.BookManager) iin); //null
}
//因为iin==null,所以此处只会生成一个代理类
return new com.lypeer.ipcclient.BookManager.Stub.Proxy(obj);
}
//返回IBinder的实现类
public android.os.IBinder asBinder() {
return this;
}
private static class Proxy implements BookManager{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
//客户端调用getBookList
public List<Book> getBookList() {
Parcel _data = android.os.Parcel.obtain();
Parcel _reply = android.os.Parcel.obtain();
List<Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//直接调用服务端transact方法
boolean _status = mRemote.transact(Stub.TRANSACTION_getBooks, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getBookList();
}
_reply.readException();
_result = _reply.createTypedArrayList(com.lypeer.ipcclient.Book.CREATOR);
}finally{
_reply.recycle();
_data.recycle();
}
return _result;
}
}
// 服务端执行onTransact根据code码进行处理
public boolean onTransact(int code,Parcel data ,Parcel reply,int flags){
java.lang.String descriptor = DESCRIPTOR;
switch(code){
case TRASACTION_getBookLIst:{
//检查客户端调用的接口是否与服务端提供的接口一致
data.enforceInterface(descriptor);
List<com.lypeer.ipcclient.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
}
}
}
}
5.3.客户端调用
public class AIDLActivity extends AppCompatActivity {
private BookManager mBookManager = null;
protected void onStart() {
attemptToBindService();
}
//尝试与服务器建立连接
private void attemptToBindService() {
Intent intent = new Intent();
intent.setAction("com.lypeer.aidl");
intent.setPackage("com.lypeer.ipcserver");
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(getLocalClassName(), "service connected");
mBookManager = BookManager.Stub.asInterface(service); //得到Proxy对象
mBound = true;
if (mBookManager != null) {
try {
mBooks = mBookManager.getBooks();
Log.e(getLocalClassName(), mBooks.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void onServiceDisconnected(ComponentName name) {
Log.e(getLocalClassName(), "service disconnected");
mBound = false;
}
};
//mBookManager.getBookList>>Proxy.getBookList>>Proxy.mRemote.onTransact(Stub.TRANSACTION_getBookList)
public getBookList(){
if(mBookManager!=null){
//回调Proxy类中的getBookList();
mBookManager.getBookList();
}
}
}
5.4.服务端实现代码
public class AIDLService extends Service{
//包含Book对象的list
private List<Book> bookList = new ArrayList<>();
//实现抽象类Stub,Stub实现了BookManager接口
private final BookManager.Stub mBookManager=new BookManager.Stub(){
public List<Book> getBookList(){
return bookList;
}
}
public void onCreate() {
Book book = new Book();
book.setName("Android开发艺术探索");
book.setPrice(28);
bookList.add(book);
super.onCreate();
}
public IBinder onBind(Intent intent) {
return mBookManager;
}
}