侧边栏壁纸
博主头像
Fup1p1 's Blog 博主等级

梦想是财富自由~

  • 累计撰写 38 篇文章
  • 累计创建 24 个标签
  • 累计收到 9 条评论

目 录CONTENT

文章目录

【Android】Android的启动流程

Fup1p1
2023-10-21 / 2 评论 / 5 点赞 / 1324 阅读 / 0 字 / 正在检测是否收录...

Init 进程 (Android 中的第一个用户进程)

当我们按下电源键时, 引导 芯片会加载运行引导程序, 引导 程序又启动 Linux 内核,在 Linux内核 加载 完成后,第一件事就是要启动 init 进程。
我们在Android中输入 ps -A | grep init ,就可以看到,init进程的PID为1
(pid=0,linux启动的第一个进程,swapper/idle进程;pid=1,init进程;pid=2,kthreadd进程)
image-1697896636413

image-1697939453591

image-1697939886775

Linux Kernel启动后,会调用init.cpp的main方法。
init进程的源码在/system/core/init/init.cpp (Android11 中 main函数被放在了/system/core/init/main.cpp)

通过阅读源码,我们可以发现init进程有两个阶段,分为 first-stage 和 second-stage
image-1697898026077

first-stage

源码位于/system/core/init/first_stage_init.cpp
主要功能不详细分析
有兴趣的看Link

  • 挂载及创建基本的文件系统,并设置合适的访问权限
  • 关闭默认控制台输出,并初始化内核级log。
  • 挂载 system、cache、data 等系统分区

image-1697898970754

second-stage

在 selinux 初始化完成后就立即重新执行main函数,进入第二阶段 second-stage,也就是将 init 进程从内核态转化为用户态执行。
image-1697898942786

对于second-stage,其也会做一些first-stage的一些工作,但是其主要做的是:初始化和启动属性服务,解析 init.rc 文件,并按顺序先后执行触发器: on early-init -> init -> late-init

低版本中直接通过init_parse_config_file(“/init.rc”); 去对init.rc进行解析,高版本则通过LoadBootScripts去解析*.rc文件,其中就包括后面zygote进程的 init.zygote.rc

image-1697899462631

加载init.rc后
又会导入init.zygotexx.rc

image-1697964499306
/system/etc/init/hw/init/init.{ro.zygote}.rc 是手机设备上的路径,和源码中的 system/core/rootdir/init.{ro.zygote}.rc是同一个文件。
image-1697972285539

init进程在解析完init.rc文件后,会依次执行触发器:on early-init -> init -> late-init。在late-init触发时,就会启动类 main 管理的服务,也就是会启动 zygote。

通过一个死循环,来保证init出来的程序的存活,所以我们如果在kill 一个 init的子进程的时候,会发现这个进程又复活了。

LoadBootScripts(am,sm),这个方法解析了一个init.rc文件,并将这些命令写到了am与sm中,在while循环里通过ExecuteOneCommand去执行这些命令
image-1697970426390

Zygote

Zygote是Java世界的创造者,Android中的所有Java进程都由Zygote进程fork而来。
Zygote本身也是由Linux系统中的init进程通过解析init.rc脚本启动的,Zygote本身其实就是app_process程序(system/bin/app_process)。

init.zygote32/64.rc(system/core/rootdir/init.zygote32/64.rc)

image-1697895174943
Service是一些在系统初始化时就启动或者退出时需要重启的程序。

其中Service用于通知init进程创建名zygote的进程,这个zygote进程执行程序的路径为/system/bin/app_process64,后面的则是要传给app_process64的参数。class main指的是zygote的class name为main。class时为服务设置类别, 非常重要, 设置之后,系统就可以批量启动或停止一类服务。

前文中提到了late-init触发时,就会启动类main管理的服务,我们来分析一下,zygote时如何启动的。

继续查看之前的init.rc文件
init.rc语法讲解

415 on late-init
416     trigger early-fs
......
442     # Now we can start zygote for devices with file based encryption
443     trigger zygote-start  //发了zygote-start事件后,就会启动zygote进程
......
810 # It is recommended to put unnecessary data/ initialization from post-fs-data
811 # to start-zygote in device's init.rc to unblock zygote start.
812 on zygote-start && property:ro.crypto.state=unencrypted
813     # A/B update verifier that marks a successful boot.
814     exec_start update_verifier_nonencrypted
815     start statsd  //// start对应的映射关系定义于system/core/init/builtins.cpp中
816     start netd
817     start zygote//// 调用start对应的处理函数,启动名为zygote的服务(传入前文init.zygote.rc中定义的参数)
818     start zygote_secondary
819 
820 on zygote-start && property:ro.crypto.state=unsupported
821     # A/B update verifier that marks a successful boot.
822     exec_start update_verifier_nonencrypted
823     start statsd
824     start netd
825     start zygote
826     start zygote_secondary
827 
828 on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
829     # A/B update verifier that marks a successful boot.
830     exec_start update_verifier_nonencrypted
831     start statsd
832     start netd
833     start zygote
834     start zygote_secondary

start 命令对应的执行函数是do_start,
///system/core/init/builtins.cpp

1330  const BuiltinFunctionMap& GetBuiltinFunctionMap() {
1331      constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
1332      // clang-format off
1333      static const BuiltinFunctionMap builtin_functions = {
.......
1382          {"start",                   {1,     1,    {false,  do_start}}},
.......
1393      };
1394      // clang-format on
1395      return builtin_functions;
1396  }

do_start函数

758  static Result<void> do_start(const BuiltinArguments& args) {
759      Service* svc = ServiceList::GetInstance().FindService(args[1]); //// 找到service 的名称找到服务
760      if (!svc) return Error() << "service " << args[1] << " not found";
761      if (auto result = svc->Start(); !result.ok()) { //调用Start函数去调用此函数
762          return ErrorIgnoreEnoent() << "Could not start service: " << result.error();
763      }
764      return {};
765  }

Start函数

392  Result<void> Service::Start() {
......
488      if (namespaces_.flags) {
489          pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
490      } else {
491          pid = fork();//通过fork函数创建zygote子进程
492      }
493  
494      if (pid == 0) {
495          umask(077);
......
522          if (!ExpandArgsAndExecv(args_, sigstop_)) {//ExpandArgsAndExecv最后也是调用execve执行子进程的代码
523              PLOG(ERROR) << "cannot execv('" << args_[0]
524                          << "'). See the 'Debugging init' section of init's README.md for tips";
525          }
526  
527          _exit(127);
528      }

Start方法中调用 fork() 创建子进程,调用 ExpandArgsAndExecv 通过最终调用 execv 执行system/bin/app_process,这样就会进入frameworks/base/cmds/app_process/app_main.cpp的main函数

app_main.cpp (frameworks\base\cmds\app_process\app_main.cpp)

#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
.........
int main(int argc, char* const argv[])
{
......
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;   //注意此处设置为true
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
.........
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//runtime.start 来启动 zygote
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

frameworks\base\core\jni\AndroidRuntime.cpp

image

ZygoteInit.java (frameworks\base\core\java\com\android\internal\os\ZygoteInit.java)

提前加载类、资源、共享库

查看main函数

image-1701352455840
提前加载资源、系统类、共享库
image-1701355344199

image-1701353179545

image-1701354128277
读取 preloaded-classes中的类,然后forName去加载系统类,在zygote中加载系统类,这样它的子进程也能访问这些系统类。

image-1701354011403

创建zygote Socket

循环监听来自 AMS 的请求,即请求开启新的APP进程
image-1701431850963

创建system_server

image-1701432097852
会去请求fork一个system server 进程
image-1701432499644
/frameworks/base/services/java/com/android/server/SystemServer.java
image-1701433021889
创建AMS PMS 两个对象
image-1701433782180

servicemanager

由init 启动,servicemanager用于管理AMS、PMS…
init.rc
image-1701434475734
frameworks\native\cmds\servicemanager\servicemanager.rc
image-1701434585194

应用启动

简要介绍一下PMS 与AMS
PMS 开机之后会遍历data/app 下目录,找到apk文件,然后解压apk,通过dom解析,最后找到包含Launcher的对应的Activity,然后存放在Package缓存里,最后mPackages集合中 ArrayMap
AMS 加载Activity并且管理 Activity
当我们要启动一个APP的时候,需要加载Activity,此时还需要PMS提供对应的信息。

image-1701483198429
当我们平时使用startActivity去启动其他应用时,startActivity会通过Binder传递包名等消息(intent)给AMS。
image-1701482696639

5

评论区