美文网首页
Binder学习笔记

Binder学习笔记

作者: 细雨么么 | 来源:发表于2023-05-25 15:52 被阅读0次

    先上学习连接:https://blog.csdn.net/qq_39867049/article/details/129816266

        ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                ITestInterface iTestInterface = ITestInterface.Stub.asInterface(iBinder);
                try {
                    iTestInterface.requestData("xx");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
        };
    

    service远程连接服务端时,会调用定义接口ITestInterface的asInterface(),asInterface是系统根据aidl文件自动生成的类,

    /*
     * This file is auto-generated.  DO NOT MODIFY.
     */
    package com.kalerm.screenTest;
    // Declare any non-default types here with import statements
    
    public interface ITestInterface extends android.os.IInterface
    {
      /** Default implementation for ITestInterface. */
      public static class Default implements com.kalerm.screenTest.ITestInterface
      {
        /**
             * 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
        {
        }
        @Override public java.lang.String requestData(java.lang.String paramters) throws android.os.RemoteException
        {
          return null;
        }
        @Override
        public android.os.IBinder asBinder() {
          return null;
        }
      }
      /** Local-side IPC implementation stub class. */
      public static abstract class Stub extends android.os.Binder implements com.kalerm.screenTest.ITestInterface
      {
        private static final java.lang.String DESCRIPTOR = "com.kalerm.screenTest.ITestInterface";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
          this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.kalerm.screenTest.ITestInterface interface,
         * generating a proxy if needed.
         */
        public static com.kalerm.screenTest.ITestInterface asInterface(android.os.IBinder obj)
        {
          if ((obj==null)) {
            return null;
          }
          android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
          if (((iin!=null)&&(iin instanceof com.kalerm.screenTest.ITestInterface))) {
            return ((com.kalerm.screenTest.ITestInterface)iin);
          }
          return new com.kalerm.screenTest.ITestInterface.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
        {
          java.lang.String descriptor = DESCRIPTOR;
          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_requestData:
            {
              data.enforceInterface(descriptor);
              java.lang.String _arg0;
              _arg0 = data.readString();
              java.lang.String _result = this.requestData(_arg0);
              reply.writeNoException();
              reply.writeString(_result);
              return true;
            }
            default:
            {
              return super.onTransact(code, data, reply, flags);
            }
          }
        }
        private static class Proxy implements com.kalerm.screenTest.ITestInterface
        {
          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);
              boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
              if (!_status && getDefaultImpl() != null) {
                getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);
                return;
              }
              _reply.readException();
            }
            finally {
              _reply.recycle();
              _data.recycle();
            }
          }
          @Override public java.lang.String requestData(java.lang.String paramters) 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);
              _data.writeString(paramters);
              boolean _status = mRemote.transact(Stub.TRANSACTION_requestData, _data, _reply, 0);
              if (!_status && getDefaultImpl() != null) {
                return getDefaultImpl().requestData(paramters);
              }
              _reply.readException();
              _result = _reply.readString();
            }
            finally {
              _reply.recycle();
              _data.recycle();
            }
            return _result;
          }
          public static com.kalerm.screenTest.ITestInterface sDefaultImpl;
        }
        static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_requestData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        public static boolean setDefaultImpl(com.kalerm.screenTest.ITestInterface 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.kalerm.screenTest.ITestInterface getDefaultImpl() {
          return Stub.Proxy.sDefaultImpl;
        }
      }
      /**
           * 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 java.lang.String requestData(java.lang.String paramters) throws android.os.RemoteException;
    }
    
    

    [图片上传中...(image.png-3b281b-1684916297352-0)]
    会先根据DESCRIPTOR查询queryLocalInterface。其中DESCRIPTOR指的是定义的aidl文件的全类名。如果是本地通讯,则返回的直接是本地的idle生成类。如果查找不到,则返回的是代理对象。ITestInterface.Stub.Proxy(obj);

    远程调用时,执行requestData。实际执行的是proxy代理对象中的requestData。

     @Override public java.lang.String requestData(java.lang.String paramters) 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);//输出全类名
              _data.writeString(paramters);//输出方法执行参数
              boolean _status = mRemote.transact(Stub.TRANSACTION_requestData, _data, _reply, 0);//mRemote 对象就是 onServiceConnected中传递过来的ibinder对象。执行transact方法,
              if (!_status && getDefaultImpl() != null) {
                return getDefaultImpl().requestData(paramters);
              }
              _reply.readException();
              _result = _reply.readString();
            }
            finally {
              _reply.recycle();
              _data.recycle();
            }
            return _result;
          }
    

    transact方法最后执行native方法,完成数据传输。


    image.png

    数据传输后,系统通知服务端stub中的 onTransact()

    //onTransact 与transact的参数一致, code 方法识别码。data,传递参数,reply 回复参数
       @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_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_requestData://执行requestdata 方法
            {
              data.enforceInterface(descriptor);
              java.lang.String _arg0;
              _arg0 = data.readString();
              java.lang.String _result = this.requestData(_arg0);//执行服务端的方法
              reply.writeNoException();
              reply.writeString(_result);//将执行结果传递回去,reply就是客户端传递过来的回复参数载体
              return true;
            }
            case TRANSACTION_requestInt:
            {
              data.enforceInterface(descriptor);
              int _result = this.requestInt();
              reply.writeNoException();
              reply.writeInt(_result);
              return true;
            }
            default:
            {
              return super.onTransact(code, data, reply, flags);
            }
          }
        }
    

    Linux系统下,一切皆文件。
    Binder其实是一个驱动文件。位于\dev\binder

    f1ed0ca9c874ba673006022db930c6fa.png

    1.init进程读取init.rc开始启动Zygote进程
    2.Zygote进程孵化fork出SystemServer进程,在SystemServer进程中
    3.反射构建出AMS服务对象,同时构建的还有PMS,WMS等
    同时

    从上往下看的.png

    ServiceManager管理 system_service中启动的一堆service服务。
    ServiceManager 通过binder 与 systemserver进行通信。

      wm = WindowManagerService.main(context, inputManager,
                        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                        !mFirstBoot, mOnlyCore, new PhoneWindowManager());
                ServiceManager.addService(Context.WINDOW_SERVICE, wm);//通过addServiceyuSeriviceManager绑定
                ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
                traceEnd();
    

    ServiceManager::class.java

    public static void addService(String name, IBinder service) {
            try {
                getIServiceManager().addService(name, service, false);
            } catch (RemoteException e) {
                Log.e(TAG, "error in addService", e);
            }
        }
    
    private static IServiceManager getIServiceManager() {
            if (sServiceManager != null) {
                return sServiceManager;
            }
    
            // Find the service manager
            sServiceManager = ServiceManagerNative
                    .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
            return sServiceManager;
        }
    
    

    系统启动流程中,init进程根据init.rc启动Zygote,然后再启动ServiceManager进程,执行service_manager.c的main方法。
    根目录: frameworks\ native\ cmds\ servicemanager\ service_manager.c

    int main(int argc, char** argv)
    {
        struct binder_state *bs;
        union selinux_callback cb;
        char *driver;
    
        if (argc > 1) {
            driver = argv[1];
        } else {
            driver = "/dev/binder";
        }
    
        bs = binder_open(driver, 128*1024)
    
      //省略...............
    }
    

    frameworks \native \cmds \servicemanager \binder.c

    struct binder_state *binder_open(const char* driver, size_t mapsize)
    {
        struct binder_state *bs;
        struct binder_version vers;
    
        bs = malloc(sizeof(*bs));
        if (!bs) {
            errno = ENOMEM;
            return NULL;
        }
    
        bs->fd = open(driver, O_RDWR | O_CLOEXEC);
        if (bs->fd < 0) {
            fprintf(stderr,"binder: cannot open %s (%s)\n",
                    driver, strerror(errno));
            goto fail_open;
        }
    
        if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
            (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
            fprintf(stderr,
                    "binder: kernel driver version (%d) differs from user space version (%d)\n",
                    vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
            goto fail_open;
        }
    
        bs->mapsize = mapsize;
        bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);//建立内存映射
        if (bs->mapped == MAP_FAILED) {
            fprintf(stderr,"binder: cannot map device (%s)\n",
                    strerror(errno));
            goto fail_map;
        }
    
        return bs;
    
    fail_map:
        close(bs->fd);
    fail_open:
        free(bs);
        return NULL;
    }
    

    虚拟内存与物理内存

    物理内存载体就是内存条???
    虚拟内存住要解决物理内存有限,而程序却越来越大需要更多的运行内存空间的问题。
    概念上来说,虚拟内存就是存储在磁盘上的 N 个连续字节的数组。磁盘上数组的内容被缓存在物理内存上(DRAM缓存)),其中的每个缓存块(cache block)就称为页(page)。

    不一定对一知半解
    磁盘被分为一个个页(一般为4k大小,内存也会这样分。目的是为了好管理),只有一部分页会放置到内存中,当CPU通过页表查找发生缺页中断时,会由中断处理程序将需要的页复制到内存中,更新页表。重新再次执行指令。??????????? image.png
    binder数据原理

    Binder机制的mmap原理就是将用户空间的虚拟地址与内核空间开辟的虚拟地址指向了同一片真实的物理地址。

    相关文章

      网友评论

          本文标题:Binder学习笔记

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