android启动流程-从开机到zygote创建
zygote进程的启动分为两大部分,native:执行Native层面的代码,这个过程主要包含:虚拟机启动,JNI资源函 数的注册,启动zygote的java层;java:执行java层面的代码,这个过程主要包含:预加载公用的各种资源,创建socket服务器并在runSelectLoop中死循环等待socket消息,fork 了systemServer进程等操作。
整体流程图
-
一、启动电源以及系统启动
-
二、引导程序Bootloader
-
三、装载和启动Linux内核
-
四、启动Init进程
main.c:
static int __ref kernel_init(void *unused)
{
...
if (execute_command) {
ret = run_init_process(execute_command);
if (!ret)
return 0;
}
if (CONFIG_DEFAULT_INIT[0] != '\0') {
ret = run_init_process(CONFIG_DEFAULT_INIT);
if (ret)
pr_err("Default init %s failed (error %d)\n",CONFIG_DEFAULT_INIT, ret);
else
return 0;
}
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;
}
static int try_to_run_init_process(const char *init_filename)
{
int ret;
ret=run_init_process(init_filename):
if(ret&&ret!=-ENOENT){
pr_err("starting init: %s exists but couldn't execute it (error %d)in",
init_filename,ret);
return ret;
}
static int run_init_process(const char *init_filename)
{
const char *const *p;
argv_init[0] = init_filename;
pr_info("Run %s as init process\n",init_filename);
pr_debug("with arguments:\n");
for(p=argv_init;*p;p++)
pr_debug("%s\n",*p);
pr_debug("with environment:\n");
for(p=envp_init;*p;p++)
pr_debug(" %s\n",+p);
return kernel_execve(init_filename,argv_init,envp_init);
}
然后执行init中的main()方法执行init进程的职责
main.cpp:
init的入口函数main.cpp;
文件位置:aosp/system/core/init/main.cpp;
执行方法:main();
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap function_map;
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
return FirstStageMain(argc, argv);
}
依次执行FirstStageMain->SetupSelinux->SecondStageMain
Init.rc:
解析init.rc:/system/core/rootdir/init.rc
在SecondStageMain中调用LoadBootScripts(am.sm)->parser.ParseConfig()->ParseConfigDir(path)&ParseConfigFile(path)->ParseData来解析init.rc;
为了保证init进程活着,有一个while(true)的死循环。epoll.Wait(epoll_timeout)等待;
init启动serviceManager:init
on init
...
# Start logd before any other services run to ensure we capture all of their logs.
start logd
# Start essential services.
start servicemanager
...
init.rc启动zygote:late-init
on late-init
//启动vold服务(管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等)
trigger early-fs
trigger fs
trigger post-fs
trigger late-fs
//挂载/data , 启动 apexd 服务
trigger post-fs-data
# 读取持久化属性或者从/data 中读取并覆盖属性
trigger load_persist_props_action
//启动zygote服务!!在启动zygote服务前会先启动netd服务(专门负责网络管理和控制的后台守护进程)
trigger zygote-start
//移除/dev/.booting 文件
trigger firmware_mounts_complete
trigger early-boot
trigger boot //初始化网络环境,设置系统环境和守护进程的权限
在init.rc文件中,执行late-init之后,启动zygote;
总结:
Init进程启动过程中,Init进程处理的重要事情:
FirstStageMain:
- 挂载Android的文件系统
- 挂载 system、cache、data 等系统分区
Selinux:
- 设置selinux安全策略
SecondStageMain:
- 初始化属性服务,注册到epoll中
- 解析init.rc
- 启动serviceManager、zygote--启动Android重要的守护进程,像usb守护进程,adb守护进程,、vold守护进程、rild守护进程
- 开启死循环,循环等待事件发生--init会变为一个守护进程执行修改属性请求,重启崩溃的进程等操作
五、启动ServiceManager
ServiceManager的主要作用是管理Binder服务,负责Binder服务的注册与查找。 ServcieManager 是一个守护进程,这个进程会一直存在于后台。当SystemServer启动 AMS,WMS,PMS等服务的时候,会将服务的binder注册到ServiceManager中,由ServcieManager来进行统一的保存。当某个进程如App进程 想调用AMS和其他进程通信的时候,就会去ServiceManager中获取AMS的b/inder,然后通过这个binder来调用AMS 的代码进行相关的操作
六、启动zygote进程
Init进程初始化结束时,会启动Zygote进程。Zygote通过fork(复制进程)的方式创建android中几乎所有的应用程序进程和SystemServer进程。另外在Zygote进程启动的时候会创建DVM或者ART虚拟机,因此使用fork而建立的应用程序进程和SystemServer进程可以在内部得到一个DVM或者ART的实例副本,这样就保障了每个app进程在Zygote fork的那一刻就有了虚拟机。
Zygote是所有应用进程的父进程:
- Zygote进程初始化时会创建Android 虚拟机、预装载系统的资源文件和Java类
- 所有从Zygote进程fork出的用户进程都将继承和共享这些预加载的资源,不用浪费时间重新加载,加快了应用程序的启动过程
- 启动结束后,Zygote进程也将变为守护进程,负责响应启动APK的请求。
Native层:
启动app_main.cpp
init.rc文件中采用了如下所示的Import类型语句来导入Zygote启动脚本:
import /init.environ.rc //导入全局环境变量
import /init.usb.rc //adb 服务、USB相关内容的定义
import /init.${ro.hardware}.rc //硬件相关的初始化,一般是厂商定制
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc //定义Zygote服务
这里根据属性ro.zygote的内容来导入不同的Zygote启动脚本。从Android 5.0开始,Android开始支持64位程序,Zygote有 了32/64位之别,ro.zygote属性的取值有4种:
init.zygote32.rc
init.zygote64.rc
init.zygote64_32.rc
init.zygote32_64.rc---在android12以后,被删除
打开zygote.rc,可以看到:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
意思就是,执行 app_process64,该程序的路径是 /system/bin/app_process64 ,类名是 main,进程名为 zygote。
查看android.bp文件可知,/system/bin/app_process对应文件就是app_main.cpp
文件路径:frameworks/base/cmds/app_process/android.bp;
执行app_main.cpp
文件路径:frameworks/base/cmds/app_process/app_main.cpp;
执行方法:
int main(int argc, char* const argv[])
{
...
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = 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);
} 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.");
}
}
可以看到,app_main根据启动时传入参数的区别,分为zygote 模式和application模式。根据下面的if判断,进入当前的zygote模式。
zygote的Native启动:
runtime.start会触发到AndroidRuntime.cpp的start方法;
文件路径:frameworks/base/core/jni/AndroidRuntime.cpp;
执行方法:start
然后通过CallStaticVoidMethod方法启动zygoteInit.java的main方法:
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
// 1.启动 java 虚拟机
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
// 2.为Java虚拟机注册JNI方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
// 3.classNameStr是传入的参数,值为com.android.internall.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
/*
4.使用toSlashClassName函数将className的 "." 替换为 "/",得到com/android/internal/os/ZygoteInit
*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
} else {
// 5.找到 ZygoteInit 中的 main 函数
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
} else {
// 6.使用JNI调用ZygoteInit的main函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
}
Zygote在启动过程中分别做了以下几件事:
- 启动java虚拟机;
- 注册android SDK需要使用的JNI方法;
- 执行ZygoteInit的main函数,进而启动zygote的java层代码,最终Zygote就从Native层 进入了Java FrameWork层。
Zygote的java执行:
文件路径:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java;
执行方法:main
执行ZygoteInit.java的main方法:
public static void main(String argv[]) {
// Server socket class for zygote processes.
ZygoteServer zygoteServer = null; //用来管理和子进程通信的socket服务端
// Mark zygote start. This ensures that thread creation will throw
// an error.
//这里其实只是设置一个标志位,为创建Java线程时做判断处理,如果是zygote进程,
//则不需要开启线程
ZygoteHooks.startZygoteNoThreadCreation();
// 代码省略...
try {
// 代码省略...
if (!enableLazyPreload) {
// 代码省略...
preload(bootTimingsTraceLog); //预加载,加快进程的启动
// 代码省略...
}
// 代码省略...
//启动socket服务,不用binder,防止死锁
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
//fork SystemServer进程,AMS由SystemServer启动
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
// 启动SystemServer
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// ZygoteServer进入无限循环,处理请求
caller = zygoteServer.runSelectLoop(abiList); //死循环,用于接收AMS传过来的消息,也保证该进程不会结束。
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket(); //关闭socket
}
}
// 代码省略...
}
zygote java层的大概流程我们已经梳理完了,现在我们来总结一下:
- 创建ZygoteServer ,这个server存在的目的是让zygote接收来自socket的请求,进而fork进程,zygoteServer 里面封装了socket。
- preload(bootTimingsTraceLog):预加载系统资源res,加载 Android sdk class资源 和其他libc。
- forkSystemServer,就是fork 产生了SystemServer进程。
- 调用 runSelectLoop() ,接收其他进程发送的socket消息,进而创建子进程。
tips:
- 调用preload完成系统资源的预加载,主要包括preloadClasses,preloadResources,preloadDrawables, preloadSharedLibraries。这些资源并不是给zygote自己实际显示使用的,它之所以存在,是为后面fork 出来的App 去运行而准备的。因为app 进程需要运行就需要framework 层的系统资源,而这些资源就会在这里得到加载。
- zygote使用跨进程通信,通过的是socket。zygote是被fork的进程,在linux中,被fork的进程通常是不允许有多线程的,因为会产生死锁的问题。
总结:
zygote进程的启动分为两大部分,
native:
执行Native层面的代码,这个过程主要包含:虚拟机启动,JNI资源函 数的注册,启动zygote的java层;
java:
执行java层面的代码,这个过程主要包含:预加载公用的各种资源,创建socket服务器并在runSelectLoop中死循环等待socket消息,fork 了systemServer进程等操作
更多推荐
所有评论(0)