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语法讲解
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
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。
评论区