Android 系统启动流程

// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();

try {
// Report Zygote start time to tron unless it is a runtime restart
if (!“1”.equals(SystemProperties.get(“sys.boot_completed”))) {
MetricsLogger.histogram(null, “boot_zygote_init”,
(int) SystemClock.elapsedRealtime());
}

// 1.加载首个Zygote进程的时候,加载参数有start-system-server,即startSystemServer=true

for (int i = 1; i < argv.length; i++) {
if (“start-system-server”.equals(argv[i])) {
startSystemServer = true;
} else if (“–enable-lazy-preload”.equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}

if (abiList == null) {
throw new RuntimeException(“No ABI list supplied.”);
}

// 2. 注册zygote服务端localserversocket
zygoteServer.registerServerSocket(socketName);

// 3.在这里开启了SystemServer,也就是Ams,Pms,Wms…等一系列系统服务
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
Log.i(TAG, “Accepting command socket connections”);

// 4.while(true) 死循环,除非抛出异常系统中断
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
} catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, “System zygote died with exception”, ex);
zygoteServer.closeServerSocket();
throw ex;
}
}

ZygoteInit.main()native层传入初始化参数调用,这里不再赘述,这边主要沿Java的framework层来分析系统的调用,结合上图和代码注释可以看到,加载参数有start-system-server,即startSystemServer=true赋值,紧接着下面会调用ZygoteServer.registerServerSocket(),也就是这里和ZygoteServer的通信用到的是LocalSocket,我们知道跨进程调用最常见的调用方式就是LocalSocketaidl,在framework里也有很多这样通信的。接下来就开启了SystemServer,后面是一个runSelectLoop(),这里其实是一个死循环,当抛出异常终止则会调用zygoteServer.closeServerSocket()来关闭socket连接。我们继续跟进startSystemServer看具体是如何开启系统服务的。

2.startSystemServer

/**

  • Prepare the arguments and fork for the system server process.
    /
    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
    throws Zygote.MethodAndArgsCaller, RuntimeException {

    /
    Hardcoded command line to start the system server */
    String args[] = {
    “–setuid=1000”,
    “–setgid=1000”,
    “–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010”,
    “–capabilities=” + capabilities + “,” + capabilities,
    “–nice-name=system_server”,
    “–runtime-args”,
    “com.android.server.SystemServer”,
    };
    ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
//传入准备参数,注意上面参数最后的"com.android.server.SystemServer"
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */

// pid = 0 说明创建子进程成功,SystemServer此时拥有独立进程,可以独立在自己的进程内操作了
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

zygoteServer.closeServerSocket();
// 处理SystemServer进程
handleSystemServerProcess(parsedArgs);
}

return true;
}

这个方法不是很长,看注释可以知道,主要是用来准备SystemServer进程的参数和forkSystemServer进程。前面一堆参数不用看,注意我添加中文注释的地方,传入的参数有一个内容为"com.android.server.SystemServer",这是SystemServer类的全限定名,接下来调用Zygote.forkSystemSeerver(),最后当pid=0时,也就是说明子进程创建成功,如果这时候有两个Zygote进程则等待第二个Zygote进程连接,关闭掉第一个Zygote进程和ZygoteServersocket连接。最后调用handleSystemServerProcess()来处理SystemServer进程。这里的Zygote.forkSystemServer()实际上是调用了native层的forkSystemServer()来fork子进程。这里主要跟进handleSystemServerProcess()看看是如何完成新fork的SystemServer进程的剩余工作的。

3.handleSystemServerProcess

/**

  • Finish remaining work for the newly forked system server process.
    */
    private static void handleSystemServerProcess(
    ZygoteConnection.Arguments parsedArgs)
    throws Zygote.MethodAndArgsCaller {

    // 默认为null,走Zygote.init()流程

if (parsedArgs.invokeWith != null) {

} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 创建类加载器,并赋予当前线程
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}

/*

  • Pass the remaining arguments to SystemServer.
    */
    ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }

/* should never reach here */
}

parsedArgs.invokeWith默认是为null的,也就是走else流程,可以看到先创建了一个类加载器并赋予了当前线程,然后进入了ZygoteInit.zygoteInit()

4.ZygoteInit.zygoteInit()

/**

  • The main function called when started through the zygote process. This
  • could be unified with main(), if the native code in nativeFinishInit()
  • were rationalized with Zygote startup.

  • Current recognized args:
    • [--] <start class name> <args>
    • @param targetSdkVersion target SDK version
    • @param argv arg strings
      */
      public static final void zygoteInit(int targetSdkVersion, String[] argv,
      ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
      if (RuntimeInit.DEBUG) {
      Slog.d(RuntimeInit.TAG, “RuntimeInit: Starting application from zygote”);
      }
    • Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “ZygoteInit”);
      RuntimeInit.redirectLogStreams();

      RuntimeInit.commonInit();
      // Zygote初始化
      ZygoteInit.nativeZygoteInit();
      // 应用初始化
      RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
      }

      这个方法不是很长,主要工作是Zygote的初始化和Runtime的初始化。Zygote 的初始化调用了native方法,里面的大致工作是打开/dev/binder驱动设备,创建一个新的binder线程,调用talkWithDriver()不断地跟驱动交互。 进入RuntimeInit.applicationInit()查看具体应用初始化流程。

      5.RuntimeInit.applicationInit

      protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
      throws Zygote.MethodAndArgsCaller {
      // If the application calls System.exit(), terminate the process
      // immediately without running any shutdown hooks. It is not possible to
      // shutdown an Android application gracefully. Among other things, the
      // Android runtime shutdown hooks close the Binder driver, which can cause
      // leftover running threads to crash before the process actually exits.
      nativeSetExitWithoutCleanup(true);

      // We want to be fairly aggressive about heap utilization, to avoid
      // holding on to a lot of memory that isn’t needed.
      VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
      VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

      final Arguments args;
      try {
      // 解析参数
      args = new Arguments(argv);
      } catch (IllegalArgumentException ex) {
      Slog.e(TAG, ex.getMessage());
      // let the process exit
      return;
      }

      // The end of of the RuntimeInit event (see #zygoteInit).
      Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

      // Remaining arguments are passed to the start class’s static main
      invokeStaticMain(args.startClass, args.startArgs, classLoader);
      }

      这个方法也不是很长,前面的一些配置略过,主要看解析参数和invokeStaticMain(),顾名思义,这里的目的是通过反射调用静态的main方法,那么调用的是哪个类的main方法,我们看传入的参数是args.startClass,我们追溯参数的传递过程,发现之前提到的一系列args被封装进ZygoteConnection.Arguments类中,这一系列参数原本是

      String args[] = {
      “–setuid=1000”,
      “–setgid=1000”,
      “–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010”,
      “–capabilities=” + capabilities + “,” + capabilities,
      “–nice-name=system_server”,
      “–runtime-args”,
      “com.android.server.SystemServer”,
      };

      可以看到,唯一的类的全限定名是com.android.server.SystemServer,追述args = new Arguments(argv)的源码也可以找到答案:

      Arguments(String args[]) throws IllegalArgumentException {
      parseArgs(args);
      }

      private void parseArgs(String args[])
      throws IllegalArgumentException {
      int curArg = 0;
      for (; curArg < args.length; curArg++) {
      String arg = args[curArg];

      if (arg.equals(“–”)) {
      curArg++;
      break;
      } else if (!arg.startsWith(“–”)) {
      break;
      }
      }

      if (curArg == args.length) {
      throw new IllegalArgumentException(“Missing classname argument to RuntimeInit!”);
      }

      // startClass 为args的最后一个参数
      startClass = args[curArg++];
      startArgs = new String[args.length - curArg];
      System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
      }
      }

      6.RuntimeInit.invokeStaticMain

      private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
      throws Zygote.MethodAndArgsCaller {
      Class<?> cl;

      try {
      cl = Class.forName(className, true, classLoader);
      } catch (ClassNotFoundException ex) {
      throw new RuntimeException(
      "Missing class when invoking static main " + className,
      ex);
      }

      Method m;
      try {
      m = cl.getMethod(“main”, new Class[] { String[].class });
      } catch (NoSuchMethodException ex) {
      throw new RuntimeException(
      "Missing static main on " + className, ex);
      } catch (SecurityException ex) {
      throw new RuntimeException(
      "Problem getting static main on " + className, ex);
      }

      int modifiers = m.getModifiers();
      if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
      throw new RuntimeException(
      "Main method is not public and static on " + className);
      }

      /*

      • This throw gets caught in ZygoteInit.main(), which responds
      • by invoking the exception’s run() method. This arrangement
      • clears up all the stack frames that were required in setting
      • up the process.
        */
        throw new Zygote.MethodAndArgsCaller(m, argv);
        }

      可以看到,这边走的就是正常的一个反射流程,会对main方法的参数、修饰符等校验,有问题抛出RuntimeException运行时异常,没问题就抛出一个Zygote.MethodAndArgsCaller,这一步的处理可以说是非常奇怪了,既然执行完毕为什么不直接invoke而是抛出异常呢,我们可以看到英文注释的大概解释,这个异常抛出在ZygoteInit.main()方法,执行了异常的run方法,其目的是清除设置中的所有堆栈帧,既然如此我们回到ZygoteInit.main()方法,果然:

      try{

      }catch (Zygote.MethodAndArgsCaller caller) {
      caller.run();
      }

      抛出该异常调用了caller.run()方法,那我们看这里做了什么:

      public static class MethodAndArgsCaller extends Exception
      implements Runnable {
      /** method to call */
      private final Method mMethod;

      /** argument array */
      private final String[] mArgs;

      public MethodAndArgsCaller(Method method, String[] args) {
      mMethod = method;
      mArgs = args;
      }

      public void run() {
      try {
      mMethod.invoke(null, new Object[] { mArgs });
      } catch (IllegalAccessException ex) {
      throw new RuntimeException(ex);
      } catch (InvocationTargetException ex) {
      Throwable cause = ex.getCause();
      if (cause instanceof RuntimeException) {
      throw (RuntimeException) cause;
      } else if (cause instanceof Error) {
      throw (Error) cause;
      }
      throw new RuntimeException(ex);
      }
      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

      深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

      因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

      img

      img

      img

      img

      既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

      由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

      如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

      最后

      跳槽季整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。

      附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

      《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

      些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。**

      附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

      [外链图片转存中…(img-Jk2wPrzI-1713763643549)]

      《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值