Android应用程序进程启动过程的源代码分析(1)

2024-06-07 21:08:41

Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制;这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的。

Android应用程序框架层创建的应用程序进程的入口函数是ActivityThread.main比较好理解,即进程创建完成之后,Android应用程序框架层就会在这个进程中将ActivityThread类加载进来,然后执行它的main函数,这个main函数就是进程执行消息循环的地方了。Android应用程序框架层创建的应用程序进程天然支持Binder进程间通信机制这个特点应该怎么样理解呢?前面我们在学习Android系统的Binder进程间通信机制时说到,它具有四个组件,分别是驱动程序、守护进程、Client以及Server,其中Server组件在初始化时必须进入一个循环中不断地与Binder驱动程序进行到交互,以便获得Client组件发送的请求,具体可参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文,但是,当我们在Android应用程序中实现Server组件的时候,我们并没有让进程进入一个循环中去等待Client组件的请求,然而,当Client组件得到这个Server组件的远程接口时,却可以顺利地和Server组件进行进程间通信,这就是因为Android应用程序进程在创建的时候就已经启动了一个线程池来支持Server组件和Binder驱动程序之间的交互了,这样,极大地方便了在Android应用程序中创建Server组件。

在Android应用程序框架层中,是由ActivityManagerService组件负责为Android应用程序创建新的进程的,它本来也是运行在一个独立的进程之中,不过这个进程是在系统启动的过程中创建的。ActivityManagerService组件一般会在什么情况下会为应用程序创建一个新的进程呢?当系统决定要在一个新的进程中启动一个Activity或者Service时,它就会创建一个新的进程了,然后在这个新的进程中启动这个Activity或者Service,具体可以参考Android系统在新进程中启动自定义服务过程(startService)的原理分析、Android应用程序启动过程源代码分析和Android应用程序在新的进程中启动新的Activity的方法和过程分析这三篇文章。

ActivityManagerService启动新的进程是从其成员函数startProcessLocked开始的,在深入分析这个过程之前,我们先来看一下进程创建过程的序列图,然后再详细分析每一个步骤。

Step 1. ActivityManagerService.startProcessLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. private final void startProcessLocked(Proce***ecord app,
  5. String hostingType, String hostingNameStr) {
  6. ......
  7. try {
  8. int uid = app.info.uid;
  9. int[] gids = null;
  10. try {
  11. gids = mContext.getPackageManager().getPackageGids(
  12. app.info.packageName);
  13. catch (PackageManager.NameNotFoundException e) {
  14. ......
  15. }
  16. ......
  17. int debugFlags = 0;
  18. ......
  19. int pid = Process.start("android.app.ActivityThread",
  20. mSimpleProcessManagement ? app.processName : null, uid, uid,
  21. gids, debugFlags, null);
  22. ......
  23. catch (RuntimeException e) {
  24. ......
  25. }
  26. }
  27. ......
  28. }

它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,后面我们会看到。

Step 2. Process.start

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

  1. public class Process {
  2. ......
  3. public static final int start(final String processClass,
  4. final String niceName,
  5. int uid, int gid, int[] gids,
  6. int debugFlags,
  7. String[] zygoteArgs)
  8. {
  9. if (supportsProcesses()) {
  10. try {
  11. return startViaZygote(processClass, niceName, uid, gid, gids,
  12. debugFlags, zygoteArgs);
  13. catch (ZygoteStartFailedEx ex) {
  14. ......
  15. }
  16. else {
  17. ......
  18. return 0;
  19. }
  20. }
  21. ......
  22. }

这里的supportsProcesses函数返回值为true,它是一个Native函数,实现在frameworks/base/core/jni/android_util_Process.cpp文件中:

  1. jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)
  2. {
  3. return ProcessState::self()->supportsProcesses();
  4. }

ProcessState::supportsProcesses函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

  1. bool ProcessState::supportsProcesses() const
  2. {
  3. return mDriverFD >= 0;
  4. }

这里的mDriverFD是设备文件/dev/binder的打开描述符,如果成功打开了这个设备文件,那么它的值就会大于等于0,因此,它的返回值为true。

回到Process.start函数中,它调用startViaZygote函数进一步操作。

Step 3. Process.startViaZygote

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

  1. public class Process {
  2. ......
  3. private static int startViaZygote(final String processClass,
  4. final String niceName,
  5. final int uid, final int gid,
  6. final int[] gids,
  7. int debugFlags,
  8. String[] extraArgs)
  9. throws ZygoteStartFailedEx {
  10. int pid;
  11. synchronized(Process.class) {
  12. ArrayList<String> argsForZygote = new ArrayList<String>();
  13. // --runtime-init, --setuid=, --setgid=,
  14. // and --setgroups= must go first
  15. argsForZygote.add("--runtime-init");
  16. argsForZygote.add("--setuid=" + uid);
  17. argsForZygote.add("--setgid=" + gid);
  18. if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
  19. argsForZygote.add("--enable-safemode");
  20. }
  21. if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
  22. argsForZygote.add("--enable-debugger");
  23. }
  24. if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
  25. argsForZygote.add("--enable-checkjni");
  26. }
  27. if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
  28. argsForZygote.add("--enable-assert");
  29. }
  30. //TODO optionally enable debuger
  31. //argsForZygote.add("--enable-debugger");
  32. // --setgroups is a comma-separated list
  33. if (gids != null && gids.length > 0) {
  34. StringBuilder sb = new StringBuilder();
  35. sb.append("--setgroups=");
  36. int sz = gids.length;
  37. for (int i = 0; i < sz; i++) {
  38. if (i != 0) {
  39. sb.append(',');
  40. }
  41. sb.append(gids[i]);
  42. }
  43. argsForZygote.add(sb.toString());
  44. }
  45. if (niceName != null) {
  46. argsForZygote.add("--nice-name=" + niceName);
  47. }
  48. argsForZygote.add(processClass);
  49. if (extraArgs != null) {
  50. for (String arg : extraArgs) {
  51. argsForZygote.add(arg);
  52. }
  53. }
  54. pid = zygoteSendArgsAndGetPid(argsForZygote);
  55. }
  56. }
  57. ......
  58. }

这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。

Step 4. Process.zygoteSendAndGetPid

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

  1. public class Process {
  2. ......
  3. private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
  4. throws ZygoteStartFailedEx {
  5. int pid;
  6. openZygoteSocketIfNeeded();
  7. try {
  8. /**
  9. * See com.android.internal.os.ZygoteInit.readArgumentList()
  10. * Presently the wire format to the zygote process is:
  11. * a) a count of arguments (argc, in essence)
  12. * b) a number of newline-separated argument strings equal to count
  13. *
  14. * After the zygote process reads these it will write the pid of
  15. * the child or -1 on failure.
  16. */
  17. sZygoteWriter.write(Integer.toString(args.size()));
  18. sZygoteWriter.newLine();
  19. int sz = args.size();
  20. for (int i = 0; i < sz; i++) {
  21. String arg = args.get(i);
  22. if (arg.indexOf('\n') >= 0) {
  23. throw new ZygoteStartFailedEx(
  24. "embedded newlines not allowed");
  25. }
  26. sZygoteWriter.write(arg);
  27. sZygoteWriter.newLine();
  28. }
  29. sZygoteWriter.flush();
  30. // Should there be a timeout on this?
  31. pid = sZygoteInputStream.readInt();
  32. if (pid < 0) {
  33. throw new ZygoteStartFailedEx("fork() failed");
  34. }
  35. catch (IOException ex) {
  36. ......
  37. }
  38. return pid;
  39. }
  40. ......
  41. }

这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:

  1. public class Process {
  2. ......
  3. /**
  4. * Tries to open socket to Zygote process if not already open. If
  5. * already open, does nothing.  May block and retry.
  6. */
  7. private static void openZygoteSocketIfNeeded()
  8. throws ZygoteStartFailedEx {
  9. int retryCount;
  10. if (sPreviousZygoteOpenFailed) {
  11. /*
  12. * If we've failed before, expect that we'll fail again and
  13. * don't pause for retries.
  14. */
  15. retryCount = 0;
  16. else {
  17. retryCount = 10;
  18. }
  19. /*
  20. * See bug #811181: Sometimes runtime can make it up before zygote.
  21. * Really, we'd like to do something better to avoid this condition,
  22. * but for now just wait a bit...
  23. */
  24. for (int retry = 0
  25. ; (sZygoteSocket == null) && (retry < (retryCount + 1))
  26. ; retry++ ) {
  27. if (retry > 0) {
  28. try {
  29. Log.i("Zygote""Zygote not up yet, sleeping...");
  30. Thread.sleep(ZYGOTE_RETRY_MILLIS);
  31. catch (InterruptedException ex) {
  32. // should never happen
  33. }
  34. }
  35. try {
  36. sZygoteSocket = new LocalSocket();
  37. sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
  38. LocalSocketAddress.Namespace.RESERVED));
  39. sZygoteInputStream
  40. new DataInputStream(sZygoteSocket.getInputStream());
  41. sZygoteWriter =
  42. new BufferedWriter(
  43. new OutputStreamWriter(
  44. sZygoteSocket.getOutputStream()),
  45. 256);
  46. Log.i("Zygote""Process: zygote socket opened");
  47. sPreviousZygoteOpenFailed = false;
  48. break;
  49. catch (IOException ex) {
  50. ......
  51. }
  52. }
  53. ......
  54. }
  55. ......
  56. }

这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。

转载于:https://blog.51cto.com/shyluo/966494

Android应用程序进程启动过程的源代码分析(1)相关推荐

  1. Android应用程序进程启动过程的源代码分析(2)

      Step 5. ZygoteInit.runSelectLoopMode         这个函数定义在frameworks/base/core/java/com/android/internal ...

  2. Android应用程序进程启动过程

    相关文章 Android系统架构与系统源码目录 Android系统启动流程(一)解析init进程启动过程 Android系统启动流程(二)解析Zygote进程启动过程 Android系统启动流程(三) ...

  3. Android系统进程Zygote启动过程的源代码分析(3)

    Step 5. ZygoteInit.startSystemServer        这个函数定义在frameworks/base/core/java/com/android/internal/os ...

  4. Android系统进程Zygote启动过程的源代码分析

    原文地址:http://blog.csdn.net/luoshengyang/article/details/6747696 Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口 ...

  5. android 启动app过程,应用程序进程启动过程

    原标题:应用程序进程启动过程 作者:慕涵盛华 链接:https://www.jianshu.com/p/b158615cc2ad 一.背景 首先注意的是:这里要说的是应用程序进程的启动过程,而不是应用 ...

  6. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  7. 从源码角度看Android系统Zygote进程启动过程

    在Android系统中,DVM.ART.应用程序进程和SystemServer进程都是由Zygote进程创建的,因此Zygote又称为"孵化器".它是通过fork的形式来创建应用程 ...

  8. 应用程序进程启动过程

    --摘自<Android进阶解密> 1.AMS在启动应用程序时会检查者应用程序需要的应用进程是否存在,不存在就会请求Zygote进程启动需要的应用程序进程 2.Zygote的Java框架层 ...

  9. [日更-2019.4.26、27、28] cm-14.1 Android系统启动过程分析(四)-应用程序进程启动过程...

    2019独角兽企业重金招聘Python工程师标准>>> 声明 前阶段在项目中涉及到了Android系统定制任务,Android系统定制前提要知道Android系统是如何启动的: 本文 ...

最新文章

  1. golang 结构体 map 转化为 json
  2. 算法——海量数据(5%)
  3. hdoop(2)——hdfs一些常用的配置文件
  4. 关于blog的编写 规则
  5. 如何关闭Windows10任务栏上的输入法提示图标
  6. leetcode1090. 受标签影响的最大值(贪心算法)
  7. Nacos 集群 Nginx MySql SpringBoot2.x 微服务_04
  8. leetcode lcp2 分式化简
  9. 【转】Cron表达式简介
  10. 强势推出第九代酷睿处理器,大敌当前,英特尔不挤牙膏了
  11. 拓端tecdat|在PYTHON中进行主题模型LDA分析
  12. C++高级进阶 第二季:mutable 关键字
  13. AAC AMR WAV MP3 采样率
  14. 物联网ARM开发高级
  15. Jrebel 最新激活方式
  16. 使用docker镜像玩转steam挂卡
  17. 360浏览器怎么设置主页
  18. 外贸软件常见图片类问题丨汇信
  19. 44万条数据揭秘:如何成为网易云音乐评论区的网红段子手?
  20. unlink快速入门

热门文章

  1. 计算机网络技术包括哪几种,计算机网络技术包含的两个主要技术是计算机技术和( )。...
  2. 女朋友存好多网上男明星的照片,我准备用python全部换成我的脸
  3. 在 Linux 中使用ImageMagick命令行操作图像文件
  4. Python中的super()用法
  5. JAVA 中 string 和 int 互相转化
  6. vue判断离开当前页面_js监听用户进入和离开当前页面
  7. python 微信公众号回复图片_Python webpy微信公众号开发之 回复图文消息
  8. 【学习笔记】和式(《具体数学》第二章)
  9. 【算法笔记】莫比乌斯反演(包含定理,两种形式的证明及入门经典模板)
  10. oracle server process,KI视角下的ORACLE SERVER PROCESS进程的活动