本文通过在字节面试遇到的问题总结而出,如有不对地方,请及时批评指正。篇幅较长,请耐心阅读
简介
当Android手机从按下开机键时,屏幕点亮,到系统桌面的显示,整个过程系统是怎么启动的?下面我们一起深入源码来看一下。整体流程如下图所示。
源码分析
init进程启动
1.BootROM
当按下电源开关键时,引导芯片程序会从预定义的地方开始执行,加载系统引导程序BootLoader到RAM,启动执行。
2.BootLoader
初始化系统硬件资源,引导操作系统启动。
3.idel进程
初始化进程管理,内存管理,加载Binder驱动,Display,Camera 驱动等相关工作。
4. init进程
Android系统启动时 通过Android.bp启动Main.cpp的main函数。
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
// 设置进程优先级
setpriority(PRIO_PROCESS, 0, -20);
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 = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
//第二次执行
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
//最后执行到 SecondStageMain
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
//firstStageMain中再次调用main.cpp,参数传为selinux_setup,后续执行SetupSelinux
return FirstStageMain(argc, argv);
Main.cpp的main方法被反复执行,最后执行到SecondStageMain方法。
int SecondStageMain(int argc, char** argv) {
.............
//初始化属性服务
PropertyInit();
// Umount the debug ramdisk after property service has read the .prop files when it means to.
if (load_debug_prop) {
UmountDebugRamdisk();
}
// Mount extra filesystems required during second stage init
MountExtraFilesystems();
// 设置系统安全策略
SelinuxSetupKernelLogging();
SelabelInitialize();
SelinuxRestoreContext();
//定义epoll机制
Epoll epoll;
if (auto result = epoll.Open(); !result.ok()) {
PLOG(FATAL) << result.error();
}
//解析init.rc文件
LoadBootScripts(am, sm);
.......................
while (true) {
// 循环等待处理
auto epoll_timeout = std::optional{};
auto shutdown_command = shutdown_state.CheckShutdown();
.........................
}
return 0;
}
} // namespace init
SecondStageMain方法中,init进程主要处理挂载文件,设置系统安全策略,开启属性服务,注册到epoll中,解析init.rc ,启动Zygote进程。
Zygote进程启动
当安卓系统启动后,会创建一个init进程,所以的进程都是有和这个init进程fork出来的,包括Zygote进程,当系统要求启动一个Android应用程序时,都会通过AMS通知Zygote进程创建一个子进程用来启动该应用程序。
1.App_main.cpp
Zygote进程启动时会执行app_main.cpp的main函数。
int main(int argc, char* const argv[])
{
.............
//初始化AppRuntime
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argc--;
argv++;
...........................
//是否是zygote进程
bool zygote = false;
//是否启动systemServer进程
bool startSystemServer = false;
bool application = false;
//进程名称
String8 niceName;
String8 className;
++i;
while (i < argc) {
const char* arg = argv[i++];
//设置zygote启动
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 (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) {
//如果是zygote进程 执行AppRuntime.start
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.");
}
}
2.AndroidRuntime.cpp
AppRuntime继承于AndroidRuntime,执行AppRuntime的start方法就是执行AndroidRuntime中的start方法。className传入的是 "
com.android.internal.os.ZygoteInit"
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
static const String8 startSystemServer("start-system-server");
//记录当前zygote是否是fork出SystemServer进程
bool primary_zygote = false;
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
//启动虚拟机
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
//如果没有虚拟机则创建新的虚拟机
onVmCreated(env);
/*
* 注册系统jni方法
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
..................
/*
* 启动虚拟机线程,执行ZygoteInit的main方法
* 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);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//执行jni方法 进入:com.android.internal.os.ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
....................
}
3.ZygoteInit.java
AndroidRuntime.start方法中 通过jni调用java代码,执行
com.android.internal.os.ZygoteInit的main方法。
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
//标记zygote进程启动
ZygoteHooks.startZygoteNoThreadCreation();
...............
Runnable caller;
try {
...................
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
//预加载资源
preload(bootTimingsTraceLog);
}
//创建zygote服务
zygoteServer = new ZygoteServer(isPrimaryZygote);
//通过zygote进程fork出SystemServer进程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
//执行SystemServer的main方法
r.run();
return;
}
}
//开启循环
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
}
ZygoteInit的main方法主要的作用是:
1).预加载系统资源。
2).创建zygote的socket服务。
3).通过Zygote进程fork出SystemServer进程。
4).执行SystemServer的main方法,启动进程。
5).zygote进入循环等待状态,接收AMS传递的消息。
Zygote作为进程孵化器,当需要启动一个程序时,首先会通过AMS使用Socket发送消息到Zygote进程,Zygote通过fork函数创建需要启动的程序进程。
以上就是字节面试后总结的几个要点,还不会的同学赶紧学起来吧,感谢您的阅读,创造不易,如果您觉得本篇文章对您有帮助,请点击关注小编,您的支持就是小编创作的最大动力!