当前位置:   article > 正文

Zygote进程启动过程_"char* slashclassname = toslashclassname(classname

"char* slashclassname = toslashclassname(classname != null ? classname : \"\");"

Zygpte 进程的启动脚本

Zygote 进程是在 init 进程启动时创建的,Zygote 的启动脚本在 system/core/rootdir 目录下,这里不详细说 init 进程启动过程了,它可以简单描述为解析 init.rc ,启动相应的脚本

init.zygote32.rc 代码

  1. #zygote配置文件相关init.rc
  2. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  3. class main
  4. priority -20
  5. user root
  6. group root readproc
  7. socket zygote stream 660 root system
  8. onrestart write /sys/android_power/request_state wake
  9. onrestart write /sys/power/state on
  10. onrestart restart audioserver
  11. onrestart restart cameraserver
  12. onrestart restart media
  13. onrestart restart netd
  14. onrestart restart wificond
  15. writepid /dev/cpuset/foreground/tasks

init 进程会调用 app_main.cpp 的 main 函数,frameworks\base\cmds\app_process\app_main.cpp

  1. int main(int argc, char* const argv[])
  2. {
  3. //...
  4. AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
  5. // Parse runtime arguments. Stop at first unrecognized option.
  6. bool zygote = false;
  7. bool startSystemServer = false;
  8. bool application = false;
  9. String8 niceName;
  10. String8 className;
  11. ++i; // Skip unused "parent dir" argument.
  12. while (i < argc) {
  13. const char* arg = argv[i++];
  14. //判断参数 arg 是否包含了 --zygote
  15. if (strcmp(arg, "--zygote") == 0) {
  16. //如果当前运行在 Zygote 进程中,则将 zygote设置为true
  17. zygote = true;
  18. niceName = ZYGOTE_NICE_NAME;
  19. } else if (strcmp(arg, "--start-system-server") == 0) {
  20. //如果包含 --start-system-server 则将 startSystemServer 设置为true
  21. startSystemServer = true;
  22. //...
  23. --i;
  24. break;
  25. }
  26. }
  27. //...
  28. if (zygote) {
  29. runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  30. } else if (className) {
  31. runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
  32. } else {
  33. fprintf(stderr, "Error: no class name or --zygote supplied.\n");
  34. app_usage();
  35. LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
  36. }
  37. }

这段代码很简单,先对参数进行判断,之后由参数调用相对应的函数,这里 zygote 为 true,调到 runtime#start 方法

frameworks/base/core/jni/AndroidRuntime.cpp

  1. void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
  2. {
  3. //...
  4. /* start the virtual machine */
  5. JniInvocation jni_invocation;
  6. jni_invocation.Init(NULL);
  7. JNIEnv* env;
  8. //创建 Java 虚拟机
  9. if (startVm(&mJavaVM, &env, zygote) != 0) {
  10. return;
  11. }
  12. onVmCreated(env);
  13. /*
  14. * Register android functions.
  15. */
  16. //为 Java 虚拟机注册 JNI 方法
  17. if (startReg(env) < 0) {
  18. ALOGE("Unable to register all android natives\n");
  19. return;
  20. }
  21. //...
  22. jclass stringClass;
  23. jobjectArray strArray;
  24. jstring classNameStr;
  25. stringClass = env->FindClass("java/lang/String");
  26. assert(stringClass != NULL);
  27. strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
  28. assert(strArray != NULL);
  29. //className 为 com.android.internal.os.ZygoteInit
  30. classNameStr = env->NewStringUTF(className);
  31. assert(classNameStr != NULL);
  32. env->SetObjectArrayElement(strArray, 0, classNameStr);
  33. //将 className 的 “.” 替换为 “/” com/android/internal/os/ZygoteInit
  34. char* slashClassName = toSlashClassName(className != NULL ? className : "");
  35. //找到这个类
  36. jclass startClass = env->FindClass(slashClassName);
  37. if (startClass == NULL) {
  38. ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
  39. /* keep going */
  40. } else {
  41. //找到 main 方法
  42. jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
  43. "([Ljava/lang/String;)V");
  44. if (startMeth == NULL) {
  45. } else {
  46. env->CallStaticVoidMethod(startClass, startMeth, strArray);
  47. #if 0
  48. if (env->ExceptionCheck())
  49. threadExitUncaughtException(env);
  50. #endif
  51. }
  52. }

AndroidRuntime#start 函数调用 ZygoteInit 中 main 方法。这里 CallStaticVoidMethod 方法是通过 JNI 调用 Java 中的方法。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 

  1. public static void main(String argv[]) {
  2. //创建 ZygoteServer
  3. ZygoteServer zygoteServer = new ZygoteServer();
  4. //...
  5. final Runnable caller;
  6. try {
  7. //...
  8. boolean startSystemServer = false;
  9. String socketName = "zygote";
  10. String abiList = null;
  11. boolean enableLazyPreload = false;
  12. //...
  13. //创建一个 Server 端的 Socket,socketName 的值为 "zygote"
  14. zygoteServer.registerServerSocket(socketName);
  15. // In some configurations, we avoid preloading resources and classes eagerly.
  16. // In such cases, we will preload things prior to our first fork.
  17. if (!enableLazyPreload) {
  18. bootTimingsTraceLog.traceBegin("ZygotePreload");
  19. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
  20. SystemClock.uptimeMillis());
  21. //预加载资源和类
  22. preload(bootTimingsTraceLog);
  23. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
  24. SystemClock.uptimeMillis());
  25. bootTimingsTraceLog.traceEnd(); // ZygotePreload
  26. } else {
  27. Zygote.resetNicePriority();
  28. }
  29. //...
  30. if (startSystemServer) {
  31. //fork SystenService进程
  32. Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
  33. // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
  34. // child (system_server) process.
  35. if (r != null) {
  36. //启动 SystemService 进程
  37. r.run();
  38. return;
  39. }
  40. }
  41. //等待 AMS 请求
  42. caller = zygoteServer.runSelectLoop(abiList);
  43. } catch (Throwable ex) {
  44. Log.e(TAG, "System zygote died with exception", ex);
  45. throw ex;
  46. } finally {
  47. zygoteServer.closeServerSocket();
  48. }
  49. if (caller != null) {
  50. caller.run();
  51. }
  52. }

ZygoteInit#main 函数主要做了4件事情:创建一个 Server 端的 Socket,预加载类和资源,启动 SystemServer进程,等待 AMS 请求创建新的应用程序。

registerServerSocket

  1. void registerServerSocket(String socketName) {
  2. if (mServerSocket == null) {
  3. int fileDesc;
  4. //拼接 Socket 的名称
  5. final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
  6. try {
  7. //得到 Socket 的环境变量
  8. String env = System.getenv(fullSocketName);
  9. //将 Socket 环境变量的值转换为文件描述符的参数
  10. fileDesc = Integer.parseInt(env);
  11. } catch (RuntimeException ex) {
  12. throw new RuntimeException(fullSocketName + " unset or invalid", ex);
  13. }
  14. try {
  15. //创建文件描述符
  16. FileDescriptor fd = new FileDescriptor();
  17. fd.setInt$(fileDesc);
  18. //创建 Socket 服务端
  19. mServerSocket = new LocalServerSocket(fd);
  20. } catch (IOException ex) {
  21. throw new RuntimeException(
  22. "Error binding to local socket '" + fileDesc + "'", ex);
  23. }
  24. }
  25. }

创建 LocalServerSocket,LocalServerSocket 的构造函数中创建 LocalSocketImpl 实现类,调用 create 方法

  1. public void create(int sockType) throws IOException {
  2. //...
  3. try {
  4. fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
  5. mFdCreatedInternally = true;
  6. } catch (ErrnoException e) {
  7. e.rethrowAsIOException();
  8. }
  9. }

这里用到了 linux 中 socket 编程。

preload

  1. static void preload(TimingsTraceLog bootTimingsTraceLog) {
  2. bootTimingsTraceLog.traceBegin("PreloadClasses");
  3. //预加载 Class
  4. preloadClasses();
  5. //预加载资源
  6. preloadResources();
  7. //OpenGL
  8. preloadOpenGL();
  9. //三方库
  10. preloadSharedLibraries();
  11. //文本资源
  12. preloadTextResources();
  13. sPreloadComplete = true;
  14. }

由名字可以看出预加载的资源有大概情况。

forkSystemServer

  1. private static Runnable forkSystemServer(String abiList, String socketName,
  2. ZygoteServer zygoteServer) {
  3. //...
  4. /* Containers run without this capability, so avoid setting it in that case */
  5. if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
  6. capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
  7. }
  8. //创建 aargs 数组,保存启动参数
  9. String args[] = {
  10. "--setuid=1000",
  11. "--setgid=1000",
  12. "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
  13. "--capabilities=" + capabilities + "," + capabilities,
  14. "--nice-name=system_server",
  15. "--runtime-args",
  16. "com.android.server.SystemServer",
  17. };
  18. ZygoteConnection.Arguments parsedArgs = null;
  19. int pid;
  20. try {
  21. parsedArgs = new ZygoteConnection.Arguments(args);
  22. pid = Zygote.forkSystemServer(
  23. parsedArgs.uid, parsedArgs.gid,
  24. parsedArgs.gids,
  25. parsedArgs.debugFlags,
  26. null,
  27. parsedArgs.permittedCapabilities,
  28. parsedArgs.effectiveCapabilities);
  29. } catch (IllegalArgumentException ex) {
  30. throw new RuntimeException(ex);
  31. }
  32. if (pid == 0) {
  33. if (hasSecondZygote(abiList)) {
  34. waitForSecondaryZygote(socketName);
  35. }
  36. zygoteServer.closeServerSocket();
  37. return handleSystemServerProcess(parsedArgs);
  38. }
  39. return null;
  40. }

先准备启动参数 args 数组,之后将 args 封装成 ZygoteConnection.Arguments 对象,最后调用 Zygote#forkSystemServer 创建子进程。

  1. public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
  2. int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
  3. VM_HOOKS.preFork();
  4. // Resets nice priority for zygote process.
  5. resetNicePriority();
  6. int pid = nativeForkSystemServer(
  7. uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
  8. // Enable tracing as soon as we enter the system_server.
  9. if (pid == 0) {
  10. Trace.setTracingEnabled(true, debugFlags);
  11. }
  12. VM_HOOKS.postForkCommon();
  13. return pid;
  14. }
  15. native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
  16. int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

这里直接调用 native 层的 nativeForkSystemServer 创建,底层也是调用了 fork() 函数。

关于 fork()

fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
    一个进程调用 fork() 函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

fork被调用一次,却能够返回两次,它可能有三种不同的返回值:

在父进程中,fork返回新创建子进程的进程ID;在子进程中,fork返回0;如果出现错误,fork返回一个负值;

runSelectLoop

  1. Runnable runSelectLoop(String abiList) {
  2. ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
  3. ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
  4. //添加到 fds 列表中
  5. fds.add(mServerSocket.getFileDescriptor());
  6. peers.add(null);
  7. //死循环
  8. while (true) {
  9. StructPollfd[] pollFds = new StructPollfd[fds.size()];
  10. //遍历 fds 将 fds 中信息转移到 pollFds 中
  11. for (int i = 0; i < pollFds.length; ++i) {
  12. pollFds[i] = new StructPollfd();
  13. pollFds[i].fd = fds.get(i);
  14. pollFds[i].events = (short) POLLIN;
  15. }
  16. try {
  17. Os.poll(pollFds, -1);
  18. } catch (ErrnoException ex) {
  19. throw new RuntimeException("poll failed", ex);
  20. }
  21. //遍历 pollFds
  22. for (int i = pollFds.length - 1; i >= 0; --i) {
  23. if ((pollFds[i].revents & POLLIN) == 0) {
  24. continue;
  25. }
  26. if (i == 0) {
  27. //通过 acceptCommandPeer 方法得到 ZygoteConnection,并添加到 peers 连接列表中
  28. ZygoteConnection newPeer = acceptCommandPeer(abiList);
  29. peers.add(newPeer);
  30. fds.add(newPeer.getFileDesciptor());
  31. } else {
  32. //...
  33. }
  34. }
  35. }
  36. }

首先调用 registerServerSocket 函数创建的服务端 Socket 获取 此Socket 设置的 fd 字段,接着无限循环遍历,注意这里 i == 0 ,说明服务器端 Socket 与客户端连接上了,也就是 Zygote 进程与 AMS 建立了连接。

Zygote的启动流程就此结束。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/227911
推荐阅读
相关标签
  

闽ICP备14008679号