概况:
- 启动init进程
- 运行init.rc
- 启动zygote服务
- Zygote fork的第一个进程——SystemServer
- SystemServer启动系统服务
1. linux启动第一个应用程序init
kernel\init\main.c
static int __ref kernel_init(void *unused)
{
int ret;
kernel_init_freeable();
async_synchronize_full();
free_initmem();
mark_readonly();
system_state = SYSTEM_RUNNING;
numa_default_policy();
flush_delayed_fput();
if (ramdisk_execute_command) {
ret = run_init_process(ramdisk_execute_command);
if (!ret)
return 0;
pr_err("Failed to execute %s (error %d)\n",
ramdisk_execute_command, ret);
}
if (execute_command) {
ret = run_init_process(execute_command);
if (!ret)
return 0;
pr_err("Failed to execute %s (error %d). Attempting defaults...\n",
execute_command, ret);
}
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/init.txt for guidance.");
}
init进程启动前的工作可以参考:https://blog.csdn.net/weixin_40535588/article/details/121221371
2. android 的init进程
不同平台的init进程不太一样,比如android的init进程源代码是放在system\core\init\init.cpp 而linux系统的一般是放在busybox的init.c中 我们先看android的init进程做了什么工作
init进程主要提供以下几个功能:
挂载文件系统、生成部分设备节点、创建目录 属性服务 处理子进程终止 分析和运行init.rc(等等rc文件)
init.rc脚本是由Android中linux的第一个用户级进程init进行解析的。
init.rc的语法参考https://blog.csdn.net/wangzaieee/article/details/84774298
最后运行了init.rc启动了安卓系统所需要的应用进程和服务
3. linux的init进程
linux系统,即大部分的嵌入式系统用的配置文件不是init.rc,而是inittab,但作用差不多,都是为了启动服务,linux系统的init进程的代码是放在busybox里init.c里
busybox被大家比作瑞士军刀,主要是它以很小的体积提供给我们很多很有用的shell指令。但是这里我们要关注的是busybox的init。
除了基本的命令之外,BusyBox还支持init功能,如同其它的init一样,busybox的init也是完成系统的初始化工作,关机前的工作等等,我们知道在Linux的内核被载入之后,机器就把控制权转交给内核,linux的内核启动之后,做了一些工作,然后找到根文件系统里面的init程序,并执行它,BusyBox的init进程会依次进行以下工作:
-
为init设置信号处理过程 -
初始化控制台 -
剖析/etc/inittab文件 -
执行系统初始化命令行,缺省情况下会使用/etc/init.d/rcS -
执行所有导致init暂停的inittab命令(动作类型:wait) -
执行所有仅执行一次的inittab(动作类型:once)
参考:https://blog.csdn.net/yangxuan12580/article/details/51372632
4. init.rc和inittab的关系
搭载linux内核的有很多平台,当内核起来后,会启动根文件系统,不同的平台,根文件系统的init进程不太一样,但是作用都是为了启动各自的服务
例如:
- 嵌入式系统的init进程代码:busybox里的init.c,配置文件是inittab
- android的init进程代码:system\core\init\init.cpp,配置文件是init.rc ubuntu
- ubuntu也会使用busybox的init进程,但是有些配置文件已经淘汰inittab,Ubuntu从6.10开始,采用Upstart替代了传统的init进程(/etc/inittab)
5. android 的init.rc的工作
参考:https://blog.csdn.net/zhonglunshun/article/details/78615980
详细可以阅读代码/system/core/rootdir/init.rc
我们主要关注init.rc去启动zygote进程
6. 启动zygote进程
参考:https://www.jianshu.com/p/a718a49f3533
zygote进程在android系统中有着及其中要的位置. 可以说android系统中的进程都是有zygote孵化出来的, 所有应用进程都是zygote的子进程.
init进启动zygote服务,zygote进程再启动其他进程. 首先,分析一下zygote服务的init.rc是如何执行的.
import /init.${ro.zygote}.rc
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=unsupported
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
将同目录下的init.zygotexx.rc文件加载. 然后根据设置条件启动zygote进程
代码文件app_main.cpp就是zygote进程的源码.
7. zyogte进程功能解析
zyogte进程大致有两个功能:
- zygote模式,也就是初始化zygote进程.
- application模式,也就是启动普通应用程序.
根据查看app_main.cpp的代码,runtime.start函数,就是要启动虚拟机了
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, 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.");
}
AndroidRuntime类
AndroidRuntime类是安卓底层系统超级重要的一个类,它负责启动虚拟机以及Java线程。AndroidRuntime类是在一个进程中只有一个实例对象,并将其保存在全局变量gCurRuntime中
start函数中主要分为两部
- 初始化jni
- 启动虚拟机
代码:
oid AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
...
}
startVm就是去启动虚拟机
8. Zygote fork的第一个进程——SystemServer
Zygote fork的第一个进程就是SystemServer,其在手机中的进程名为 system_server。
system_server 进程承载着整个framework的核心服务,例如创建 ActivityManagerService、PowerManagerService、DisplayManagerService、PackageManagerService、WindowManagerService、LauncherAppsService等80多个核心系统服务。这些服务以不同的线程方式存在于system_server这个进程中。
参考: https://blog.csdn.net/yiranfeng/article/details/103550262
SystemServer fork流程分析
- Zygote启动后fork的第一个进程为SystemServer,在手机中的进程别名为"system_server",主要用来启动系统中的服务
- Zygote fork后,进入SystemServer的main()
- SystemServer在启动过程中,先初始化一些系统变量,加载类库,创建Context对象,创建- SystemServiceManager对象等候再启动服务
- 启动的服务分为 引导服务(Boot Service)、核心服务(Core Service)和其他服务(Other Service)三大类,共90多个服务
- SystemServer在启动服务前,会尝试与Zygote建立Socket通信,通信成功后才去启动服务
启动的服务都单独运行在SystemServer的各自线程中,同属于SystemServer进程
|