Android IPC Binder机制学习(一)

这篇具有很好参考价值的文章主要介绍了Android IPC Binder机制学习(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、多进程系统设计及意义

Android系统分为5层,不过Android一般岗位只关注上三层就够用了即:应用层、framework层、native层。

  1. Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。

  1. Android中不同的应用属于不同的进程中

Android应用和系统服务运行在不同的进程中是为了安全、稳定、及内存管理的原因,但应用和系统服务需要通信和分享数据。

优点

  • 安全性:每个进程都可以单独运行,可以保证应用层对系统层的隔离。

  • 稳定性:如果某个进程崩溃了不会导致其他进程崩溃

  • 内存分配:如果某个进程已经不需要了,可以从能存中移除,并回收相应的内存。

以上优点都是将系统设计成多进程的原因,我们在开发App时,也可以根据需要将App也设计成多进程的,比如以下场景:

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

  • 突破进程内存限制,如图库占用内存过多

  • 功能稳定性:独立的通信进程保持长连接的稳定性(如:微信的消息推送功能跑在独立的进程)

  • 规避系统内存泄漏:独立的webview进程阻隔内存泄漏导致的问题

  • 隔离风险:对于不稳定的功能放入独立的进程,避免导致主进程崩溃

二、Android/Linux都有哪些进程间通信方式?Android为什么主要采用Binder作为进程间的通信方式?

  1. 内存共享

Android IPC Binder机制学习(一)
  1. 管道

Android IPC Binder机制学习(一)
  1. 消息队列

Android IPC Binder机制学习(一)
  1. socket

Android IPC Binder机制学习(一)
  1. binder

Android IPC Binder机制学习(一)

疑问1:共享内存和内存映射有什么区别?

共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)

内存映射用于文件读写:当多个进程映射到同一个文件时,并且设置了MAP_SHARE,此时可以IPC,不过数据会写回磁盘,所以还是共享内存快。

疑问2:为什么binder通信要将数据拷贝到内核空间,再由内核空间和server端做内存映射,而不是client和server直接做内存映射?

答:有两点1是拷贝到内核会对uid和pid等进行身份检测,权限安全,2是有一次拷贝,这就是个单向操作,server端哪怕修改了内存映射中的数据,也不会影响到client端中的数据,保证数据安全。

各种方式对比

Android IPC Binder机制学习(一)

三、Binder通信模型(以请求系统服务为例如ActivityManagerService)

Android IPC Binder机制学习(一)
  1. Android系统服务在启动后会将自己注册到ServiceManager,ServiceManager维护了一个表来存储各种系统服务的名字和binder(系统服务名和系统服务的binder(可理解为系统服务的句柄)是对应关系)。

  1. 客户度想要请求系统服务时,要向serviceManager中传对应的系统服务名来获取对应的系统服务Binder。

  1. 客户端有了系统服务的binder就可以通过Binder驱动向系统服务发送数据,从而完成了跨进程通信。

  1. 客户端向服务端发送的数据中会携带客户端的binder,这样服务端如果有数据需要返回给客户端,就可以通过客户端的binder来实现。

四、Binder是怎么创建的?

1.要讨论Binder是怎么创建的,需要先清楚Binder是什么?

在Android中我们所使用的Activity,Service等组件都需要和AMS通信,这种跨进程的通信都是通过Binder完成的。

  • 机制:Binder是一种进程间的通信机制

  • 驱动:Binder是一个虚拟物理设备驱动

  • 应用层:Binder是一个能发起通信的Java类

  • Framework/native:Binder连接了Client、Server、ServiceManager和Binder驱动程序,形成一套C/S的通信架构

2.Binder是什么时候创建的呢?

在进程创建的时候,就准备了binder

以Service Manager进程为例:

//文件路径:frameworks\native\cmds\servicemanager\main.cpp
int main(int argc, char** argv) {
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }

    //此时要使用的binder驱动为 "/dev/binder"
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
    //初始化binder驱动
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
    //实例化ServiceManager
    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
    //将自身作为服务添加
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }
    //设置服务端Bbinder对象
    IPCThreadState::self()->setTheContextObject(manager);
    //设置称为binder驱动的context manager,称为上下文的管理者
    ps->becomeContextManager(nullptr, nullptr);
    //通过Looper epoll机制处理binder事务
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);

    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

五、Binder的使用

通常我们使用Binder并不是直接使用,因为Binder的使用较为复杂容易出问题,由此Android官方出了一个对Binder的封装框架即AIDL。

可以先看下AIDL的简单使用

Android IPC Binder机制学习(一)

通过AIDL文件生成的接口中,内部类Stub提供了服务端提供的服务的实现逻辑,Proxy是Stub的代理类,用于给客户端提供调用服务端Stub的句柄。在使用demo中也能看到AIDL文件在客户端和服务端中都要用到(且内容相同),但在客户端与服务端中使用的部分是不一样的,Proxy是给客户端使用的,Stub是服务端使用的,或者说Stub是服务端所持有的。(注意这个service不是我们自己的service而是AMS)

六、Binder跨进程传递数据的详细流程

Android IPC Binder机制学习(一)

上图概括出了从Activity要拿到我们自己service的Binder的过程,要经过8次跨进程通信

这里我们以上图中①处的从App进程到servicemanager进程获取AMS的IBinder的操作为例,来具体分析Binder跨进程通信的过程。其中会涉及servicemanager的启动流程相关的内容,不熟悉的小伙伴可以先看一下。

  1. 客户端发送请求数据到内核中的Binder驱动

//入口代码
Activity中调用startService()

//最终会调用到ContextImpl.java中的
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // ActivityManager.getService() 就是本小节分析的重点,跨进程获取AMS的IBinder
            ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service,
                    service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                    getOpPackageName(), getAttributionTag(), user.getIdentifier());
        ...
}

// ActivityManager.java
@UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    //这里正式进入主题,这行代码大家都很熟悉吧
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

//ServiceManager.java

public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                //缓存中到不到,走这里
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

 // name是一层层传递进来的,ACTIVITY_SERVICE = "activity"
 private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();
        //这里分为两步
        // step1:getIServiceManager() 拿到servicemanager的IBinder
        // step2:getService(name) 这一步就是跨进程通信了
        final IBinder binder = getIServiceManager().getService(name);
        ...
        return binder;
 }

 //----------------------先看step1:---------------------------
 private static IServiceManager getIServiceManager() {
        //不为空直接返回
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface( //注解1
                 Binder.allowBlocking(
                     BinderInternal.getContextObject()  //注解2
                     ) 
                 );
        return sServiceManager;
  }

  //先看注解2:    BinderInternal.java
  //是个native方法,由此进入native层源码
  public static final native IBinder getContextObject();

//寻找getContextObject()对应对的native方法,了解过Android系统启动流程的小伙伴知道在启动zygote进程的
//时候(frameworks\base\cmds\app_process\app_main.cpp),有一个非常重要的步骤就是会进行一系列的jni方法注册,
//我们来具体看下
//main方法
int main(int argc, char* const argv[])
{
    ...
     if (zygote) {
        //启动运行时环境
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
      }
}

//进入start()      frameworks\base\core\jni\AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    if (startReg(env) < 0) {  //注册JNI
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
} 

int AndroidRuntime::startReg(JNIEnv* env)
{
   
    ...
    // gRegJNI 是定义好的jni方法 相关的结构体数组,系统中所有需要动态加载的jni方法都在这了
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    ...

    return 0;
}

static const RegJNIRec gRegJNI[] = {
   ...
   //这个也有一定的规律,我们要寻找的BinderProxy.transactNative()的包名就是android.os,它是binder相关的jni
   REG_JNI(register_android_os_Binder),  
   ...
}
//   frameworks\base\core\jni\android_util_Binder.cpp  进入register_android_os_Binder这个方法
int register_android_os_Binder(JNIEnv* env)
{
    if (int_register_android_os_Binder(env) < 0)
        return -1;
    if (int_register_android_os_BinderInternal(env) < 0) //在这个方法里注册BinderInternal.java中的native方法
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0) 
        return -1;
    ...
}

//看和java类对应上了吧
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
     ... 
    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
        gBinderInternalMethods, NELEM(gBinderInternalMethods));
}

//重点在这里,这个数组中写死了java方法与native方法的对应关系,(jni动态注册)
static const JNINativeMethod gBinderInternalMethods[] = {
     /* name, signature, funcPtr */
    //android_os_BinderInternal_getContextObject就是我们要找的native方法
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
    { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc },
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
};

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    //将b转成java中的对象
    return javaObjectForIBinder(env, b);  //注解3
}

//frameworks\native\libs\binder\ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    sp<IBinder> context = getStrongProxyForHandle(0);
    ...
    return context;
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
    handle_entry* e = lookupHandleLocked(handle);

    if (e != nullptr) {
        IBinder* b = e->binder;
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            // //创建BpBinder并保存下来以便后面再次查找
            //ServiceManager 服务比较特殊,其BBinder(服务)保存在IPCThreadState中(the_context_object),对应的handle 是0;
            //ServiceManager的BBinder在每一个进程中的handle值都为0。因此,任何进程和ServiceManager进程的通信便不再需要事先获取它的代理对象,
            //而只需要告诉Binder Driver:我需要和handle值为0的进程通信。Binder Driver便会自动将该进程的通信请求转发到ServiceManager进程。 
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
     }
   ...
   }
    //最终将servicemanager的BBinder的代理对象BpBinder返回了出去
    return result;
}

//接下来看注解3处的流程,将得到的BpBinder转换成Java层使用的对象
// 将一个BpBinder对象(这是native中的类型)转换成java中的类型
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
     ...
     //通过反射创建java 对应的BpBinder对象(BinderProxy)
     jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
     ...
}

//gBinderProxyOffsets.mClass就是反射创建对象的类型,它是在下面的方法中被赋值的
const char* const kBinderProxyPathName = "android/os/BinderProxy";

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    ...
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
            "(JJ)Landroid/os/BinderProxy;");
    gBinderProxyOffsets.mSendDeathNotice =
            GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
                                   "(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
    gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
    ...
}


/**回到注解2处,我们知道BinderInternal.getContextObject() = BinderProxy对象
  *实质上是servicemanager进程中创建的BBinder对象
  *                                java层 | native层                     
  *封装关系ServicemanagerProxy->BinderProxy->BpBinder == BBinder
  *此时再来看注释1处,其实就是
  *sServiceManager = ServiceManagerNative.asInterface(BinderProxy对象) //伪代码
 **/
//ServiceManagerNative.java

public static IServiceManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }

        // ServiceManager is never local
        return new ServiceManagerProxy(obj);
}

//java层的servicemanager的IBinder代理类

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;  //BinderProxy
        //熟悉AIDL的小伙伴应该知道,IServiceManager这个类就是通过IServiceManager.aidl文件生成的,下面会给出这个文件
        mServiceManager = IServiceManager.Stub.asInterface(remote);
    }

    //注意,后面step2就是走到这个方法
    public IBinder getService(String name) throws RemoteException {
        // Same as checkService (old versions of servicemanager had both methods).
        return mServiceManager.checkService(name);
    }

    private IBinder mRemote;
    private IServiceManager mServiceManager;  //IServiceManager.Stub.Proxy类型
}

//---------------------------step2----------------------------
/**回到step2处,
  *private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();
        //这里分为两步
        // step1:getIServiceManager() 拿到servicemanager的IBinder
        // step2:getService(name) 这一步就是跨进程通信了
        //由上可知getIServiceManager() = ServiceManagerNative.ServiceManagerProxy对象
        final IBinder binder = getIServiceManager().getService(name);
        ...
        return binder;
    }
**/

//getService(name)会调到ServiceManagerNative.ServiceManagerProxy.getService()
public IBinder getService(String name) throws RemoteException {
        //mServiceManager是IServiceManager.Stub.Proxy类型的对象
        return mServiceManager.checkService(name);
}

//为了方便分析,我们可以使用aidl工具将IserviceManager.aidl的java类生成出来:
//内容较多只截取当前需要的部分代码
public interface IServiceManager extends android.os.IInterface
{
 
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements android.os.IServiceManager
  {
    private static final java.lang.String DESCRIPTOR = "android.os.IServiceManager";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an android.os.IServiceManager interface,
     * generating a proxy if needed.
     */
    public static android.os.IServiceManager asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof android.os.IServiceManager))) {
        return ((android.os.IServiceManager)iin);
      }
      return new android.os.IServiceManager.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
      return this;
    }
    
    private static class Proxy implements android.os.IServiceManager
    {
      private android.os.IBinder mRemote; //BinderProxy
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
      @Override public android.os.IBinder asBinder()
      {
        return mRemote;
      }
      public java.lang.String getInterfaceDescriptor()
      {
        return DESCRIPTOR;
      }
      
      
      @Override public android.os.IBinder checkService(java.lang.String name) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        android.os.IBinder _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeString(name);
          //_data中写入了我们传的那么参数,mRemote的类型是BinderProxy,TRANSACTION_checkService代表当前要跨进程执行的是checkService()这个函数        
          boolean _status = mRemote.transact(Stub.TRANSACTION_checkService, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().checkService(name);
          }
          _reply.readException();
          _result = _reply.readStrongBinder();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      
      public static android.os.IServiceManager sDefaultImpl;
    }
    static final int TRANSACTION_getService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_checkService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
   
}

//来到BinderProxy类的transact()
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
       ...
        try {
            //主线流程来到transactNative(),他是一个native方法,
            final boolean result = transactNative(code, data, reply, flags);

            if (reply != null && !warnOnBlocking) {
                reply.addFlags(Parcel.FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT);
            }

            return result;
        } 
        ...
 }

//由此将从java层调用到native层
public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;


//4.寻找transactNative()对应对的native方法,了解过Android系统启动流程的小伙伴知道在启动zygote进程的
//时候(frameworks\base\cmds\app_process\app_main.cpp),有一个非常重要的步骤就是会进行一系列的jni方法注册,
//我们来具体看下:
//main方法
int main(int argc, char* const argv[])
{
    ...
     if (zygote) {
        //启动运行时环境
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
      }
}

//进入start()      frameworks\base\core\jni\AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    if (startReg(env) < 0) {  //注册JNI
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
} 

int AndroidRuntime::startReg(JNIEnv* env)
{ 
    ...
    // gRegJNI 是定义好的jni方法 相关的结构体数组,系统中所有需要动态加载的jni方法都在这了
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    ...

    return 0;
}

static const RegJNIRec gRegJNI[] = {
   ...
   //这个也有一定的规律,我们要寻找的BinderProxy.transactNative()的包名就是android.os,它是binder相关的jni
   REG_JNI(register_android_os_Binder),  
   ...
}
//   frameworks\base\core\jni\android_util_Binder.cpp  进入register_android_os_Binder这个方法
int register_android_os_Binder(JNIEnv* env)
{
    if (int_register_android_os_Binder(env) < 0)
        return -1;
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0) //android.os.BinderProxy中的jni方法
        return -1;
    ...
}

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    //通过反射技术进行动态注册
    ...
    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

//JNINativeMethod这个结构体封装了java方法与native方法的对应关系,及方法签名
static const JNINativeMethod gBinderProxyMethods[] = {
     /* name, signature, funcPtr */
    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
    {"getNativeFinalizer",  "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
    {"getExtension",        "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
};

//android_os_BinderProxy_transact就是我们要寻找的目标,当java层调用BinderProxy的transactNative(),就会调到这个native方法:
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
   ...
   //这里就是将java层的BinderProxy对象转换为native层的BpBinder对象
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
   ...
   //调用BpBinder的transact()
   status_t err = target->transact(code, *data, reply, flags);
}

//进入transact()    frameworks\native\libs\binder\BpBinder.cpp
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    ...
    status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
    ...
}

//进入transact()  frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
   ...
   if (reply) { 
            err = waitForResponse(reply); //即我们跨进程执行的函数时有返回值的
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
} 

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    ...
    while(1){
        //读写binder驱动
        if ((err=talkWithDriver()) < NO_ERROR) break;
    }
}

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ...
    //这里的ioctl就是系统操作了,这里完成的操作就是将用户空间的数据写到内核空间中的binder驱动中
    ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);
    ...
}
  1. 将binder驱动中的数据发送到服务端

在servicemanager进程启动流程中提到,在servicemanager启动后,注册了回调方法来监听binder驱动中是否有数据写入,并开启Looper等待处理客户端发送(写入)的数据,在上一节中已经将数据写到驱动中,接下来进入监听函数:

//文件路径 frameworks\native\cmds\servicemanager\main.cpp     
class BinderCallback : public LooperCallback {
public:

    // 当binder驱动发来消息后,就可以通过次函数接收处理了
    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        //处理消息
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

继续来看收到消息后的具体处理:

// frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::handlePolledCommands()
{
    status_t result;
    // 当读缓存中数据未消费完时,持续循环
    do {
        result = getAndExecuteCommand();
    } while (mIn.dataPosition() < mIn.dataSize());

    // 当我们清空执行完所有的命令后,最后处理BR_DECREFS和BR_RELEASE
    processPendingDerefs();
    flushCommands();
    return result;
}

继续跟进:

status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;
    // 从binder驱动中读写数据并写入mIn(理论来说此时写缓存dataSize为0,也就是只读数据)
    result = talkWithDriver();
    ...
    cmd = mIn.readInt32();
    //执行读到的命令
    result = executeCommand(cmd);
    ...
}

executeCommand()主要任务就是根据binder驱动中读出的命令去执行对应的操作:

status_t IPCThreadState::executeCommand(int32_t cmd)
{
   switch ((uint32_t)cmd) {
      ...
      //以本案例,是处理这个命令
      case BR_TRANSACTION:
        {
            ...
            Parcel buffer;
            //读取数据到缓冲区
            //实例化了一个Parcel对象作为缓冲区,从binder_transaction_data中将实际数据读取出来
            buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
            Parcel reply;
           
            //对于ServiceManager的binder节点来说,是没有ptr的
            if (tr.target.ptr) {
                // We only have a weak reference on the target object, so we must first try to
                // safely acquire a strong reference before doing anything else with it.
                // 对于其他binder服务端来说,tr.cookie为本地BBinder对象指针
                if (reinterpret_cast<RefBase::weakref_type*>(
                        tr.target.ptr)->attemptIncStrong(this)) {
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else { //对于serviceManager来说the_context_object就是BBinder对象,
                     //在main()中创建了ServiceManager对象并赋值给了the_context_object
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }
            ...
        }
        break;
 
   }


}

但我们在ServiceManager中并没有找到transact()方法,它定义在ServiceManager的父类BnServiceManager的父类Binder(Binder.cppframeworks\native\libs\binder\Binder.cpp)中:

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        ...
        //进到这里
        default:
            err = onTransact(code, data, reply, flags);
            break;
    }
    ...
    return err;
}

而在它的子类中重写了onTransact(),来到BnServiceManager,但这个类不在AOSP中,而是通过

(frameworks\native\libs\binder\aidl\android\os\IserviceManager.aidl)生成的:

::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
  ::android::status_t _aidl_ret_status = ::android::OK;
  switch (_aidl_code) {
      case ::android::IBinder::FIRST_CALL_TRANSACTION + 1 /* checkService */:
  {
    ...
    // 这里调用的是子类(即实现类 ServceManager)的checkService(0
    ::android::binder::Status _aidl_status(checkService(in_name, &_aidl_return));
    ...
  }
  break;
  }
}

来到frameworks\native\cmds\servicemanager\ServiceManager.cpp

Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
    *outBinder = tryGetService(name, true);
    // returns ok regardless of result for legacy reasons
    return Status::ok();
}

sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
    auto ctx = mAccess->getCallingContext();

    sp<IBinder> out;
    Service* service = nullptr;
    //在android系统初始化的时候,所有的系统服务启动后都会以键值对的方式注册(保存)到ServiceManager中的mNameToService集合中
    //这里的name是我们从java层传递下来的Context.ACTIVITY_SERVICE = “activity”,他对应的是ActivityManagerService的Binder对象
    if (auto it = mNameToService.find(name); it != mNameToService.end()) {
        service = &(it->second);

        if (!service->allowIsolated) {
            uid_t appid = multiuser_get_app_id(ctx.uid);
            bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;

            if (isIsolated) {
                return nullptr;
            }
        }
        out = service->binder;
    }

    if (!mAccess->canFind(ctx, name)) {
        return nullptr;
    }

    if (!out && startIfNotFound) {
        tryStartService(name);
    }

    if (out) {
        // Setting this guarantee each time we hand out a binder ensures that the client-checking
        // loop knows about the event even if the client immediately drops the service
        service->guaranteeClient = true;
    }

    return out;
}

到此将AMS的Binder对象返回给了客户端,有了AMS的Binder对象就可以使用AMS提供的服务(功能)了。

下图画出了跨进程通信中每层的关键流程。

Android IPC Binder机制学习(一)

七、AIDL文件生成c++文件文章来源地址https://www.toymoban.com/news/detail-407366.html

#aidl程序  设置生成的语言  aidl文件路径 aidl文件        输出路径   头文件输出路径
#sdk/build-tools
aidl.exe  --lang=cpp -I E:\src E:\src\test.aidl -o E:\dst --head_out E:\dst

到了这里,关于Android IPC Binder机制学习(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C/C++ 进程间通信system V IPC对象超详细讲解(系统性学习day9)

    目录 前言 一、system V IPC对象图解 1.流程图解: ​编辑 2.查看linux内核中的ipc对象:  二、消息队列 1.消息队列的原理 2.消息队列相关的API 2.1 获取或创建消息队列(msgget)  实例代码如下: 2.2 发送消息到消息队列中  实例代码如下: 2.3 从消息队列中获取消息   实例代码如

    2024年02月08日
    浏览(24)
  • 【Android Framework系列】第2章 Binder机制大全

       Binder是Android中主要的跨进程通信方式 。Android系统中,每个应用程序是由Android的Activity,Service,BroadCast,ContentProvider这四剑客中一个或多个组合而成,这四剑客所涉及的多进程间的通信底层都是依赖于BinderIPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需

    2024年02月10日
    浏览(34)
  • Android Binder机制浅谈以及使用Binder进行跨进程通信的俩种方式(AIDL以及直接利用Binder的transact方法实现)

    Binder机制学习 ·为何新增Binder来作为主要的IPC方式 Android也是基于Linux内核,Linux现有的进程通信手段有管道/消息队列/共享内存/套接字/信号量。 既然有现有的IPC方式,为什么重新设计一套Binder机制呢? 主要是出于以上三个方面的考量: 2. binder是什么? 从进程间通信的角度

    2024年02月16日
    浏览(26)
  • Android组件间的交互和进程间IPC通信(1),【吐血整理】

    openSomeDiagIntent.setAction(“edwin.demo.fooActivity”); this.startActivity(openSomeDiagIntent); 上面的隐式消息不包含具体的目的地,而是仅包含一个名位“Action”的特征字符串,Action就是上文所说的Intent特征的一种。从字面上来理解,可以理解为这个消息所代表的是完成某一个动作的含义,由

    2024年04月26日
    浏览(26)
  • 【Android车载系列】第9章 车载通信-Socket实现IPC通信机制(实现仿FDBus效果)

      FDBus 基于 Socket (TCP 和 Unix domain) 之上的IPC机制, 采用 Google protobuf 做序列化和反序列化。 FDBus还支持字符串形式的名字作为server地址。通过 name server 自动为 server 分配Unix domain 地址和 TCP 端口号, 实现 client 和server 之间用服务名字寻址。 一句话描述:FDBus (Fast Distributed Bus

    2024年02月10日
    浏览(34)
  • (25)Linux IPC 进程间通信&&系统调用:pipe接口

    我们在之前讲过 \\\"进程之间是具有独立性\\\" 的,如果进程间想交互数据,成本会非常高! 因为独立性之本质即 \\\"封闭\\\",进程们你封闭你的我封闭我的,那么进程间的交流可谓是窒碍难行。 进程间的通信说白了就是 \\\"数据交互\\\",我们需要多进程进行协同处理一件事情。 刚才说的

    2024年02月02日
    浏览(26)
  • 【看表情包学Linux】IPC 进程间通信 | PIPE 管道 | 匿名管道 | 管道通信的原理 | 系统调用: pipe 接口

       🤣  爆笑 教程  👉 《看表情包学Linux》 🔥 CSDN 累计订阅量破千的火爆 C/C++ 教程的 2023 重制版,C 语言入门到实践的精品级趣味教程。 了解更多: 👉  \\\"不太正经\\\" 的专栏介绍  ← 试读第一章 订阅链接: 🔗 《C语言趣味教程》 ← 猛戳订阅! 目录 Ⅰ. 进程间通信(I

    2024年02月14日
    浏览(28)
  • 【安卓源码】Binder机制3 -- Binder线程池

    Binder本身是C/S架构,就可能存在多个Client会同时访问Server的情况。 在这种情况下,如果Server只有一个线程处理响应,就会导致客户端的请求可能需要排队而导致响应过慢的现象发生。解决这个问题的方法就是引入多线程。【多个客户端不同线程去请求,服务端需要使用多线程

    2023年04月27日
    浏览(47)
  • 微服务学习笔记--高级篇--(多级缓存意义及JVM进程缓存)

    亿级流量的缓存方案 传统缓存的问题 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,存在下面的问题: 请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈 Redis缓存失效时,会对数据库产生冲击 多级缓存方案 多级缓存就是充分利用请求处

    2024年02月09日
    浏览(31)
  • 基于Java(Springboot框架) 后台课程学习小程序系统设计与实现研究背景与意义、国内外研究现状

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、

    2024年02月03日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包