Init 进程 (Android 中的第一个用户进程)
当我们按下电源键时, 引导 芯片会加载运行引导程序, 引导 程序又启动 Linux 内核,在 Linux内核 加载 完成后,第一件事就是要启动 init 进程。
我们在Android中输入 ps -A | grep init ,就可以看到,init进程的PID为1
(pid=0,linux启动的第一个进程,swapper/idle进程;pid=1,init进程;pid=2,kthreadd进程)
Linux Kernel启动后,会调用init.cpp的main方法。 init进程的源码在/system/core/init/init.cpp (Android11 中 main函数被放在了/system/core/init/main.cpp)
通过阅读源码,我们可以发现init进程有两个阶段,分为 first-stage 和 second-stage
first-stage
源码位于/system/core/init/first_stage_init.cpp 主要功能不详细分析 有兴趣的看Link
- 挂载及创建基本的文件系统,并设置合适的访问权限
- 关闭默认控制台输出,并初始化内核级log。
- 挂载 system、cache、data 等系统分区
second-stage
在 selinux 初始化完成后就立即重新执行main函数,进入第二阶段 second-stage,也就是将 init 进程从内核态转化为用户态执行。
对于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
加载init.rc后 又会导入init.zygotexx.rc
/system/etc/init/hw/init/init.{ro.zygote}.rc 是手机设备上的路径,和源码中的 system/core/rootdir/init.{ro.zygote}.rc是同一个文件。
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去执行这些命令
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)
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语法讲解
start 命令对应的执行函数是do_start, ///system/core/init/builtins.cpp
do_start函数
Start函数
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)
frameworks\base\core\jni\AndroidRuntime.cpp
ZygoteInit.java (frameworks\base\core\java\com\android\internal\os\ZygoteInit.java)
提前加载类、资源、共享库
查看main函数
提前加载资源、系统类、共享库
读取 preloaded-classes中的类,然后forName去加载系统类,在zygote中加载系统类,这样它的子进程也能访问这些系统类。
创建zygote Socket
循环监听来自 AMS 的请求,即请求开启新的APP进程
创建system_server
会去请求fork一个system server 进程
/frameworks/base/services/java/com/android/server/SystemServer.java
创建AMS PMS 两个对象
servicemanager
由init 启动,servicemanager用于管理AMS、PMS......
init.rc
frameworks\native\cmds\servicemanager\servicemanager.rc
应用启动
简要介绍一下PMS 与AMS PMS 开机之后会遍历data/app 下目录,找到apk文件,然后解压apk,通过dom解析,最后找到包含Launcher的对应的Activity,然后存放在Package缓存里,最后mPackages集合中 ArrayMap AMS 加载Activity并且管理 Activity 当我们要启动一个APP的时候,需要加载Activity,此时还需要PMS提供对应的信息。
当我们平时使用startActivity去启动其他应用时,startActivity会通过Binder传递包名等消息(intent)给AMS。
评论区