Android Zygote进程启动流程

Posted by Jfson on 2017-05-23

Zygote进程简介

什么是Zygote进程? Zygote进程 是整个Android系统的根进程,包括SystemServer进程和所有应用进程在内都是通过Zygote进程 fork 出来的。Zygote进程则是通过Linux系统init进程启动。

  • 启动顺序: Linux系统init进程 –> Zygote进程 –> SystemServer进程 –> Application 进程
  • init进程:Android系统第一个进程,也是linux的根进程,主要用于初始化各种文件系统,输入输出系统,log系统等等设备相关联的初始化
  • Zygote进程:Android系统的根进城,用于fork除SystemServer进程和各种应用进程
  • SystemServer进程 –> 启动ActivityManagerService,WindowManagerService,PowerManagerService等等各项服务
  • Application 进程: App 应用进程

源码分析(Android 6.0)

  • 1.从ZygoteInit main()方法中开始看。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public static void main(String argv[]) {
try {
RuntimeInit.enableDdms();
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = 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.");
}
registerZygoteSocket(socketName);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gcAndFinalize();
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
  • 从上面可以看到主要做了哪几件事

    • 1.1 enableDdms() 设置DDMS可用

    • 1.2 for 循环,解析是否需要启动SystemService进程;获取abi列表;获取socket连接名称

    • 1.3 registerZygoteSocket(String socketName) 为Zygote 进程注册socket;(PS:Android中进程间通都是用Binder,但是有一个例外,SystemService进程与Zygote进程之间是通过Socket的方式进行通讯的)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      private static void registerZygoteSocket(String socketName) {
      if (sServerSocket == null) {
      int fileDesc;
      final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
      try {
      String env = System.getenv(fullSocketName);
      fileDesc = Integer.parseInt(env);
      } catch (RuntimeException ex) {
      throw new RuntimeException(fullSocketName + " unset or invalid", ex);
      }
      try {
      FileDescriptor fd = new FileDescriptor();
      fd.setInt$(fileDesc);
      sServerSocket = new LocalServerSocket(fd);
      } catch (IOException ex) {
      throw new RuntimeException(
      "Error binding to local socket '" + fileDesc + "'", ex);
      }
      }
      }
    • 1.4 preload(),可以看到
      preloadClasses 初始化Zygote所需的类
      preloadResources 初始化通用系统资源
      preloadOpenGL 初始化OpenGL
      preloadSharedLibraries 初始化 shared libraries
      preloadTextResources 初始化文字资源
      prepareWebViewInZygote 初始化WebView(必须是Zygote进程)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      static void preload() {
      Log.d(TAG, "begin preload");
      preloadClasses();
      preloadResources();
      preloadOpenGL();
      preloadSharedLibraries();
      preloadTextResources();
      // Ask the WebViewFactory to do any initialization that must run in the zygote process,
      // for memory sharing purposes.
      WebViewFactory.prepareWebViewInZygote();
      Log.d(TAG, "end preload");
      }
    • 1.5 SamplingProfilerIntegration.writeZygoteSnapshot() 存储一下zygote进程快照
      gcAndFinalize() fork之前调用下系统GC

    • 1.6 startSystemServer(abiList, socketName),接下来就是fork SystemServer进程了
      通过Zygote.forkSystemServe() fork 出SystemServer进程
    • 1.7 关闭Socket
      handleSystemServerProcess 当fork出SystemServer后关闭socket

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      private static boolean startSystemServer(String abiList, String socketName)
      throws MethodAndArgsCaller, RuntimeException {
      long capabilities = posixCapabilitiesAsBits(
      OsConstants.CAP_BLOCK_SUSPEND,
      OsConstants.CAP_KILL,
      OsConstants.CAP_NET_ADMIN,
      OsConstants.CAP_NET_BIND_SERVICE,
      OsConstants.CAP_NET_BROADCAST,
      OsConstants.CAP_NET_RAW,
      OsConstants.CAP_SYS_MODULE,
      OsConstants.CAP_SYS_NICE,
      OsConstants.CAP_SYS_RESOURCE,
      OsConstants.CAP_SYS_TIME,
      OsConstants.CAP_SYS_TTY_CONFIG
      );
      /* 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,1032,3001,3002,3003,3006,3007",
      "--capabilities=" + capabilities + "," + capabilities,
      "--nice-name=system_server",
      "--runtime-args",
      "com.android.server.SystemServer",
      };
      ZygoteConnection.Arguments parsedArgs = null;
      int pid;
      try {
      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 */
      if (pid == 0) {
      if (hasSecondZygote(abiList)) {
      waitForSecondaryZygote(socketName);
      }
      handleSystemServerProcess(parsedArgs);
      }
      return true;
      }
      /**
      * Finish remaining work for the newly forked system server process.
      */
      private static void handleSystemServerProcess(
      ZygoteConnection.Arguments parsedArgs)
      throws ZygoteInit.MethodAndArgsCaller {
      closeServerSocket();
      // set umask to 0077 so new files and directories will default to owner-only permissions.
      Os.umask(S_IRWXG | S_IRWXO);
      if (parsedArgs.niceName != null) {
      Process.setArgV0(parsedArgs.niceName);
      }
      final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
      if (systemServerClasspath != null) {
      performSystemServerDexOpt(systemServerClasspath);
      }
      if (parsedArgs.invokeWith != null) {
      String[] args = parsedArgs.remainingArgs;
      // If we have a non-null system server class path, we'll have to duplicate the
      // existing arguments and append the classpath to it. ART will handle the classpath
      // correctly when we exec a new process.
      if (systemServerClasspath != null) {
      String[] amendedArgs = new String[args.length + 2];
      amendedArgs[0] = "-cp";
      amendedArgs[1] = systemServerClasspath;
      System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
      }
      WrapperInit.execApplication(parsedArgs.invokeWith,
      parsedArgs.niceName, parsedArgs.targetSdkVersion,
      VMRuntime.getCurrentInstructionSet(), null, args);
      } else {
      ClassLoader cl = null;
      if (systemServerClasspath != null) {
      cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
      Thread.currentThread().setContextClassLoader(cl);
      }
      /*
      * Pass the remaining arguments to SystemServer.
      */
      RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
      }
      /* should never reach here */
      }

梳理一下流程

流程图


pv UV: