本篇分析针对系统android-11.0.0_r28版本 先来张图:
init流程
android内核启动首先会调用init的main.c类
android-kernel/common/init/main.c
//内核空间init方法 1409行
static int __ref kernel_init(void *unused) {
//等待kthread全部设置完毕
wait_for_completion(&kthreadd_done);
//需要在释放内存之前完成所有async _init代码
async_synchronize_full();
//内核映射现在已经完成—更新用户空间页表 完成PTI
pti_finalize();
//**初始化方法,这是我们主要关心的方法,会调用系统init
!try_to_run_init_process("/bin/init") ||
}
然后调用到system/core/init/main.cpp
//反复执行多次
int main(int argc, char** argv) {
if (!strcmp(argv[1], "selinux_setup")) {
//2.挂载linux安全子系统,安全策略
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
//3.初始化属性
return SecondStageMain(argc, argv);
}
}
//1.第一阶段方法
return FirstStageMain(argc, argv);
}
//第一阶段
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
//安全处理 重启信号
InstallRebootSignalHandlers();
}
//在initramdisk中完成我们需要的基本文件系统设置
//其余在rc文件中完成
//主要是挂载文件,对文件系统初始化
CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
//mkdir创建文件夹
CHECKCALL(mkdir("/dev/pts", 0755));
//日志初始化
InitKernelLogging(argv);
//最后定义目录和selinux_setup,走到第二阶段,安全子系统
const char* path = "/system/bin/init";
const char* args[] = {path, "selinux_setup", nullptr};
xecv(path, const_cast<char**>(args));
//第二阶段
int SetupSelinux(char** argv) {
//设置SELinux,加载SELinux策略
SelinuxSetupKernelLogging();
SelinuxInitialize();
//第二阶段主要是做安全策略相关,然后调用了第三阶段的方法
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
}
//第三阶段(可以叫第二主阶段)
int SecondStageMain(int argc, char** argv) {
//输入输出打印 logging
SetStdioToDevNull(argv);
InitKernelLogging(argv);
//******初始化属性域
PropertyInit();
//查看是否需要加载调试道具以允许adb root,当设备被解锁。
const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
//挂载第二阶段初始化期间所需的额外文件系统
MountExtraFilesystems();
//处理子进程终止信号
InstallSignalFdHandler(&epoll);
InstallInitNotifier(&epoll);
StartPropertyService(&property_fd);
//****负载启动脚本 解析init.rc文件
LoadBootScripts(am, sm);
//死循环等待
while (true) {
//等待触发
auto pending_functions = epoll.Wait(epoll_timeout);
}
}
//看下LoadBootScripts方法中做了什么 parse很多init文件
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
........
if (!parser.ParseConfig("/vendor/etc/init")) {
late_import_paths.emplace_back("/vendor/etc/init");
}
} else {
parser.ParseConfig(bootscript);
}
}
//ParseConfig 最终都走入了ParseConfigFile方法
bool Parser::ParseConfig(const std::string& path) {
if (is_dir(path.c_str())) {
return ParseConfigDir(path);//最终走入ParseConfigFile
}
return ParseConfigFile(path);
}
//根据传入文件的各种state解析init文件
void Parser::ParseData(const std::string& filename, std::string* data) {
for (;;) {
switch (next_token(&state)) {
case T_EOF:
section_parser->EndFile();
return;
case T_NEWLINE:
}
//
在第二个主阶段最后,执行了很多init文件和init.rc文件,什么作用。
进入system/core/rootdir/init.rc看一下
# Now we can start zygote for devices with file based encryption
//现在我们可以开始zygote设备基于文件加密触发zygote-start
trigger zygote-start
可以看到zygote的启动实在init的第二个主阶段,执行了init.rc完成的。
init.rc 1.执行zygote 2.执行重启。
在看下init(pid=0)中我们做了什么事情?
- 挂载文件
- 设置seliunx --安全子模块、安全策略
- 开启属性服务,注册到epoll中
- 解析init.rc文件
- 循环处理脚本 ----这一步,对zygote进行启动
- 最后while(true)等待
Zygote流程
可以看到zygote有好多文件,32位的加载zygote32,64位系统加载zygote64,32-64就是先尝试加载32,然后加载64,反之亦然。
目录system/core/rootdir/init.zygote64_32.rc 以init.zygote64为例
//可以看到加载了手机中 /system/bin/app_process64这个目录的文件,并传入参数
service zygote /system/bin/app_process64
-Xzygote /system/bin --zygote --start-system-server
搜索一下,app_process可以看到 adnroid.bp文件 frameworks/base/cmds/app_process/Android.bp
执行的是:srcs: ["app_main.cpp"]
native层
//进入app_main.cpp,直接找main函数
//直接执行了 AppRuntime : public AndroidRuntime
//开启了android运行时环境
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
//264行的两个判断,可以看到rc文件中的两个参数
//--zygote --start-system-server
//到这里zygote、startSystemServer都被置为true
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
//0.执行到
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
//frameworks/base/core/jni/AndroidRuntime.cpp
//1.先启动虚拟机
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
//2.注册jni函数
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//点击startReg方法,可以看到执行了
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0)
//可以看到for循环取数组中的函数
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0)
//gRegJNI 看看REG_JNI数组中的几个函数,是我们非常熟悉的。
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
//3.最后调用ZygoteInit,在0.的时候我们把类名传进来的
//startClass == com.android.internal.os.ZygoteInit
env->CallStaticVoidMethod(startClass, startMeth, strArray);
//会调用到ZygoteInit中的方法
java层
main(){
// ZygotePreload 预加载,加快进程的启动
preload(bootTimingsTraceLog);
//Server socket class for zygote processes.
zygoteServer = new ZygoteServer(isPrimaryZygote); // socket
Runnable r = forkSystemServer // 启动 SystemServer 进程
//在runSelectLoop开启死循环,接收AMS传过来的消息
caller = zygoteServer.runSelectLoop(abiList);
}
Zygote总结:
native:
- 初始化运行环境,创建jvm android虚拟机
- 注册jni函数
- 调用 zygote.init类 main方法
java:
- 预加载,加快进程启动
- 启动zygote socket
- 创建systemserver
- 循环等待