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层面进行了

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值