美文网首页
Binder机制原理

Binder机制原理

作者: Owen270 | 来源:发表于2024-11-13 18:07 被阅读0次

1.Binder是什么?

  • 机制:Binder是一种进程间通信机制。
  • 驱动:Binder是一个虚拟物理设备驱动
  • 应用层:Binder是一个能够发起通信的java类

2.多进程的使用以及优势

虚拟机分配给各个进程的运行内存是有限制的,LMK也会优先回收对系统资源占用多的进程

  • 突破进程内存限制
  • 功能稳定性 ,独立的通信进程保持长连接的稳定性。(极光推送,百度定位)
  • 规避系统内存泄漏:独立的WebView进程阻隔内存泄漏导致的问题。
  • 隔离风险,对于不稳定的功能放入到独立进程,避免导致主进程的崩溃.

3.Linux中进程间的通信机制有哪些?与传统的IPC机制相比,有哪些优势?

1732615212620.png

Binder 共享内存 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.png

4.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;
      }
}

相关文章

网友评论

      本文标题:Binder机制原理

      本文链接:https://www.haomeiwen.com/subject/yaydjjtx.html