android 13 Zygote fork新的app进程源码分析-车载车机手机framework实战开发

hi,粉丝朋友们!
今天有个学员朋友在千里马的android framework实战开发时候,使用的是最新android13代码的,相比以前的版本这块Zygote fork新进程还是有较大的差异。
下面我们就来重点分析一下android13的zygote的fork App进程源码分析,主要讲解和以前版本差异部分:

在这里插入图片描述

上图就是老版本的一个fork情况
但是新版本android 13后在ZygoteConnection.processCommand的部分开始有很大差异

//这里android 13要非常特殊应用才可以进入这里,一般都是else
  if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
                        || !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
    
    
                    // Continue using old code for now. TODO: Handle these cases in the other path.
                    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
                            parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
                            parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
                            fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
                            parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
                            parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
                            parsedArgs.mBindMountAppStorageDirs);

                    //省略
                } else {
    
    
                //普通app都是走这里
                    ZygoteHooks.preFork();
                    Runnable result = Zygote.forkSimpleApps(argBuffer,
                            zygoteServer.getZygoteSocketFileDescriptor(),
                            peer.getUid(), Zygote.minChildUid(peer), parsedArgs.mNiceName);
                    //省略
                }

哈哈,注意一般app都是走Zygote.forkSimpleApps这个,但是你要是对这个方法直接打印会发现它并不是个一次性方法,进入后马上出来,这里forkSimpleApps方法名字其实和它的实际行动不太搭,所以这里大家特别注意不要被它的名字迷惑,以为每次 fork新的app进程,这里就会进入一次forkSimpleApps

来看看forkSimpleApps的特殊

    static @Nullable Runnable forkSimpleApps(@NonNull ZygoteCommandBuffer argBuffer,
                                             @NonNull FileDescriptor zygoteSocket,
                                             int expectedUid,
                                             int minUid,
                                             @Nullable String firstNiceName) {
    
    
        boolean in_child =
                argBuffer.forkRepeatedly(zygoteSocket, expectedUid, minUid, firstNiceName);
        if (in_child) {
    
    
            return childMain(argBuffer, /*usapPoolSocket=*/null, /*writePipe=*/null);
        } else {
    
    
            return null;
        }
    }

这里看着没有啥东西,就是调用了个argBuffer.forkRepeatedly方法,不过这个方法就可以看出点有循环的意思

boolean forkRepeatedly(FileDescriptor zygoteSocket, int expectedUid, int minUid,
                       String firstNiceName) {
    
    
        try {
    
    
            return nativeForkRepeatedly(mNativeBuffer, zygoteSocket.getInt$(),
                    expectedUid, minUid, firstNiceName);
        } finally {
    
    
            Reference.reachabilityFence(mSocket);
            Reference.reachabilityFence(zygoteSocket);
        }
    }

这里又调用到了nativeForkRepeatedly

jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
            JNIEnv* env,
            jclass,
            jlong j_buffer,
            jint zygote_socket_fd,
            jint expected_uid,
            jint minUid,
            jstring managed_nice_name) {
    
    
  //省略部分
  do {
    
    
    if (credentials.uid != expected_uid) {
    
    
      return JNI_FALSE;
    }
    n_buffer->readAllLines(first_time ? fail_fn_1 : fail_fn_n);
    n_buffer->reset();
    int pid = zygote::forkApp(env, /* no pipe FDs */ -1, -1, session_socket_fds,
                              /*args_known=*/ true, /*is_priority_fork=*/ true,
                              /*purge=*/ first_time);//这里进行zygote::forkApp
    if (pid == 0) {
    
    
      return JNI_TRUE;//新fork的进程直接退出
    }
 //zygote自身继续监听数据循环
    for (;;) {
    
    //注意这里死循环
      // Poll isn't strictly necessary for now. But without it, disconnect is hard to detect.
      //一般就会一直阻塞这里,等待下一个要fork进程时候就可以继续执行
      int poll_res = TEMP_FAILURE_RETRY(poll(fd_structs, 2, -1 /* infinite timeout */));
      if ((fd_structs[SESSION_IDX].revents & POLLIN) != 0) {
    
    
        if (n_buffer->getCount(fail_fn_z) != 0) {
    
    //有新的进程fork时候,会break出这个死循环
          break;
        }  // else disconnected;
      }
      //省略
    }
    first_time = false;
  } while (n_buffer->isSimpleForkCommand(minUid, fail_fn_n));
  ALOGW("forkRepeatedly terminated due to non-simple command");
  n_buffer->logState();
  n_buffer->reset();
  return JNI_FALSE;
}

上面即可以看出,这一部分的循环数据监测工作放到的native层面进行了

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/learnframework/article/details/130651589