• Android 启动流程及 init 进程解析


    一、Android 启动流程概括

    按下电源键触发开机,从 ROM 加载引导程序 BootLoader 到 RAM 中,BootLoader 执行启动 Linux kernel,然后启动第一个用户进程 init,init 进程的工作包括挂载文件、创建文件目录、设置 selinux 安全策略,解析 init.rc 脚本等。随后 init 进程会启动 Zygote 进程,Zygote 进程做一些资源预加载的工作,并启动 SystemServer 进程。SystemServer 进程作为 Socket 服务端,启动包括 AMS、WMS、PMS 等 90 多个服务在内的系统服务。在众多服务启动完毕后,AMS 会打开 Launcher 应用的 Home Activity,进入手机桌面。

    附:kernel 的初始化流程(详细代码自行下载 linux kernel 源码)

    传统的加载器包含两个文件

    init.s:初始化堆栈,调用 main.c 的 main() 函数

    main.c:初始化硬件(主板、闹钟等),创建 linux 标签

    当内核完成系统设置后,会在系统文件中寻找 init 文件。

    Dir:kernel/common/init/main.c

    (1)执行 kernel_init() 函数

    (2)启动 /bin/init  文件:try_to_run_init_process("/bin/init");

    (3)try_to_run_init_process() ---> run_init_process()--->kernel_execve()

    init/android.bp 中指明了 init 的入口函数:init/main.cpp,随后会执行 main.cpp 中的 main 方法


    二、init 进程的启动流程

    Dir:system/core/init/main.cpp ---> main() 方法

    FirstStageMain() ---- SetupSelinux() ---- SecondStageMain()

    第一阶段

    FirstStageMain()
    1、mount()--挂载文件、mkdir()--创建文件目录
    2、SetStdioToDevNull()--重定向标准输入输出
    3、InitKernelLogging()--初始化内核日志
    4、启动 setupSelinux

    SetupSelinux()
    配置安全策略 -- 对应安卓的权限策略

    第二阶段

    SecondStageMain()
    1、初始化属性系统

    PropertyInit()


    2、监听子进程的终止信号,释放资源,防止僵尸进程

    1. InstallSignalFdHandler(&epoll);
    2. InstallInitNotifier(&epoll);
    3. StartPropertyService(&property_fd);


    3、匹配 linux 命令和实际执行函数之间的关系

    GetBuiltinFunctionMap()


    4、解析 init.rc

    1. LoadBootScripts(am, sm)
    2. -->CreateParser() //创建解析器
    3. -->//添加 rc 文件的解析组件 service、on、import
    4. parser.AddSectionParser("service", std::make_unique(&service_list, GetSubcontext(), std::nullopt));
    5. parser.AddSectionParser("on", std::make_unique(&action_manager, GetSubcontext()));
    6. parser.AddSectionParser("import", std::make_unique(&parser));
    7. -->//解析 rc 文件
    8. parser.ParseConfig("/system/etc/init/hw/init.rc");
    9. -->ParserConfigDir-->ParserConfigFile
    10. -->ParserConfigFile
    11. -->ParserData


    5、While(true) 循环监听
     

    auto pending_functions = epoll.Wait(epoll_timeout);


    总结:init 进程处理的事情:
    1、 挂载文件
    2、设置 selinux -- 安全策略
    3、开启属性服务,注册到 epoll 中
    4、解析 init.rc
    5、循环处理脚本,包括启动 zygote
    6、循环等待

                    
    启动 Service 的过程

    1. /system/core/rootdir/init.rc
    2. -->
    3. on nonencrypted
    4. class_start main --> do_class_start(const BuiltinArguments& args)
    5. class_start late_start
    6. /system/core/init/builtins.cpp
    7. -->do_class_start(const BuiltinArguments& args)
    8. -->StartIfNotDisabled()
    9. /system/core/init/service.cpp
    10. -->StartIfNotDisabled()
    11. -->Start()

    三、Zygote 启动流程

    1、触发 Zygote

    Dir:/system/core/rootdir/init.rc

    (1)init.rc 中引入的 zygote.rc 脚本

    import /system/etc/init/hw/init.${ro.zygote}.rc
    不同的 rc 配置文件对应不同的启动策略
    根据不同厂商共有四个属性:
    init.zygote32.rc  -- 执行 app_process
    init.zygote64.rc --执行 app_process64
    init.zygote32_64.rc -- 启动两个 zygote 进程,名为 zygote 和 zygote_secondary,分别执行 app_process32、app_process64
    init.zygote64_32.rc -- -- 启动两个 zygote 进程,名为 zygote 和 zygote_secondary,分别执行 app_process64、app_process32


    (2)zygote 触发时机

    1. on late-init
    2. -->trigger zygote-start
    3. on zygote-start
    4. -->start zygote
    5. Dir:/system/core/init/init.cpp
    6. if (bootmode == "charger") {
    7. am.QueueEventTrigger("charger");
    8. } else {
    9. am.QueueEventTrigger("late-init");
    10. }

    附:app_process 位于手机系统的 bin 目录下,在 AS File Explorer 中可以看到,app_process 会
    读取到 /frameworks/base/cmds/app_process/Android.bp 文件,然后执行 app_main.cpp,
    /frameworks/base/cmds/app_process/app_main.cpp 的 main 方法解析的参数,则来源于 init.zygote.rc

    2、Zygote 初始化

    Dir:/frameworks/base/cmds/app_process/app_main.cpp
    (1)main() 进行参数解析【--zygote  --start-system-server】

    1. if (strcmp(arg, "--zygote") == 0) {
    2. zygote = true;
    3. niceName = ZYGOTE_NICE_NAME;
    4. }
    5. if (zygote) {
    6. runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    7. }

    (2)创建虚拟机及注册 JNI

    Dir:frameworks/base/core/jni/AndroidRuntime.cpp

    1. startVm() -- 创建虚拟机
    2. startReg() -- 注册 JNI
    3. --> register_jni_procs(gRegJNI, NELEM(gRegJNI), env) //gRegJNI 是一个 jni 数组对象
    4. env->CallStaticVoidMethod(startClass, startMeth, strArray); //startClass 即传入的ZygoteInit
    5. //接下来就会执行 ZygoteInit.java 的 main 方法,从 native 层进入 java 层
    6. //JVM :虚拟机,其实就是一块代码,负责实现内存管理,因为是 zygote 通过 fork 创建的进程,所以每个进程都拥有一个独立的 JVM

    3、Zygote 的 java 启动

    (1)预加载,加快 app 进程的启动

    Dir:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java -- main()

    1. preload(bootTimingsTraceLog);
    2. 1)bootTimingsTraceLog.traceBegin("PreloadClasses");
    3. //preloadClassess 将framework.jar里的preloaded-classes 定义的所有class load到内存里,preloaded-classes 编译Android后可以在framework/base下找到。
    4. //会加载手机 system/etc/preloaded-classes 文件中记录好的类文件
    5. 2)preloadResources();
    6. //preloadResources 将系统的Resource(不是在用户apk里定义的resource)load到内存。资源preload到Zygoted的进程地址空间,所有fork的子进程将共享这份空间而无需重新load, 这大大减少了应用程序的启动时间,但反过来增加了系统的启动时间。通过对preload 类和资源数目进行调整可以加快系统启动。Preload也是Android启动最耗时的部分之一

    (2)通知 VM 进行垃圾回收

    1. //gc()必须在fork之前完成(接下来的StartSystemServer就会有fork操作),这样将来被复制出来的子进程才能有尽可能少的垃圾内存没有释放
    2. gcAndFinalize();

    (3)创建 zygote 服务端,本质上是一个 socket

    1. //frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    2. zygoteServer = new ZygoteServer(isPrimaryZygote);
    3. -->
    4. //frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    5. mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
    6. -->
    7. //frameworks/base/core/java/com/android/internal/os/Zygote.java
    8. return new LocalServerSocket(fd);

     

    (4)创建 SystemServer 进程

    1. Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
    2. ZygoteInit.java--forkSystemServer()
    3. -->Zygote.java--nativeForkSystemServer()
    4. -->com_android_internal_os_Zygote_nativeForkSystemServer.cpp【通过 JNI 的映射】
    5. -->pid_t pid = zygote::ForkCommon(env, true,fds_to_close,fds_to_ignore,true);
    6. -->pid_t pid = fork(); //最终调用 linux 的 fork()

    (5)循环等待

    caller = zygoteServer.runSelectLoop(abiList);


    四、SystemServer 启动流程

    1、参数处理

    1. //ZygoteInit.java
    2. //在 handleSystemServerProcess() 中进行 server 的初始化工作
    3. if (pid == 0) {
    4. if (hasSecondZygote(abiList)) {
    5. waitForSecondaryZygote(socketName);
    6. }
    7. zygoteServer.closeServerSocket();
    8. return handleSystemServerProcess(parsedArgs);
    9. }
    10. //(1) prepareSystemServerProfile(systemServerClasspath);
    11. //(2) 判断fork args 中是否有 invokWith 参数,如果有则进行WrapperInit.execApplication
    12. if (parsedArgs.mInvokeWith != null) {
    13. String[] args = parsedArgs.mRemainingArgs;
    14. // If we have a non-null system server class path, we'll have to duplicate the
    15. // existing arguments and append the classpath to it. ART will handle the classpath
    16. // correctly when we exec a new process.
    17. if (systemServerClasspath != null) {
    18. String[] amendedArgs = new String[args.length + 2];
    19. amendedArgs[0] = "-cp";
    20. amendedArgs[1] = systemServerClasspath;
    21. System.arraycopy(args, 0, amendedArgs, 2, args.length);
    22. args = amendedArgs;
    23. }
    24. WrapperInit.execApplication(parsedArgs.mInvokeWith,
    25. parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
    26. VMRuntime.getCurrentInstructionSet(), null, args);
    27. throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
    28. } else {
    29. ClassLoader cl = getOrCreateSystemServerClassLoader();
    30. if (cl != null) {
    31. Thread.currentThread().setContextClassLoader(cl);
    32. }
    33. /*
    34. * Pass the remaining arguments to SystemServer.
    35. */
    36. return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
    37. parsedArgs.mDisabledCompatChanges,
    38. parsedArgs.mRemainingArgs, cl);
    39. }

    2、初始化

    (1) ZygoteInit

    1. //ZygoteInit.java
    2. ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);
    3. -->
    4. ZygoteInit.nativeZygoteInit();
    5. -->
    6. //JNI
    7. com_android_internal_os_ZygoteInit_nativeZygoteInit
    8. -->
    9. //AndroidRuntime.cpp
    10. gCurRuntime->onZygoteInit();
    11. -->
    12. //app_main.cpp
    13. virtual void onZygoteInit(){
    14. sp proc = ProcessState::self();
    15. ALOGV("App process: starting thread pool.\n");
    16. //启动一个 Binder 线程池,用于 SystemServer 和其他线程的通信
    17. proc->startThreadPool();
    18. }

    (2)applicationInit

    1. //ZygoteInit.java
    2. return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);
    3. -->
    4. //RuntimeInit.java
    5. return findStaticMain(args.startClass, args.startArgs, classLoader);
    6. -->
    7. //RuntimeInit.java; 通过反射找到SystemServer 的 main 方法
    8. m = cl.getMethod("main", new Class[] { String[].class });
    9. return new MethodAndArgsCaller(m, argv);
    10. //耗时操作通过线程完成,MethodAndArgsCaller 的 run 方法中执行
    11. mMethod.invoke(null, new Object[] {null, new Object[]{ mArgs });
    12. -->
    13. //SystemServer 的 main 方法执行:
    14. public static void main(String[] args) {
    15. new SystemServer().run();
    16. }

    五、SystemServer 执行流程

    1、初始化

    (1)一些属性的设置

    (2)初始化上下文

    1. // Initialize the system context.
    2. createSystemContext();
    3. private void createSystemContext() {
    4. ActivityThread activityThread = ActivityThread.systemMain();
    5. mSystemContext = activityThread.getSystemContext();
    6. mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
    7. final Context systemUiContext = activityThread.getSystemUiContext();
    8. systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    9. }

    2、创建 SystemServiceManager

    1. //初始化SystemServiceManager,用来管理启动service,SystemServiceManager中封装了启动Service的startService方法启动系统必要的Service
    2. mSystemServiceManager = new SystemServiceManager(mSystemContext);

    3、启动一系列系统服务

    1. try {
    2. t.traceBegin("StartServices");
    3. startBootstrapServices(t);
    4. startCoreServices(t);
    5. startOtherServices(t);
    6. startApexServices(t);
    7. } catch (Throwable ex) {
    8. Slog.e("System", "******************************************");
    9. Slog.e("System", "************ Failure starting system services", ex);
    10. throw ex;
    11. } finally {
    12. t.traceEnd(); // StartServices
    13. }
  • 相关阅读:
    大数据ClickHouse(二十):ClickHouse 可视化工具操作
    c++ 11 recursive_mutex 递归锁
    Spring 事务失效的八种场景
    30天Python入门(第三天:深入了解Python中的运算符)
    Vue3.0路由拦截
    面经记录—浩x
    【专栏】基础篇04| Redis 该怎么保证数据不丢失(上)
    力扣刷题记录53.1-----700. 二叉搜索树中的搜索
    函数传址,但无法改变xy数据问题
    什么年代了还在手工写接口测试文档吗?
  • 原文地址:https://blog.csdn.net/Jacinth40/article/details/136294510