Android 启动流程及 init 进程解析

本文详细介绍了Android设备启动过程,包括BootLoader加载kernel,init进程的初始化、selinux策略设置,Zygote进程和SystemServer的启动,以及关键组件如app_process和zygote.rc文件的参与。
摘要由CSDN通过智能技术生成

一、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、监听子进程的终止信号,释放资源,防止僵尸进程

InstallSignalFdHandler(&epoll);
InstallInitNotifier(&epoll);
StartPropertyService(&property_fd);


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

GetBuiltinFunctionMap()


4、解析 init.rc

LoadBootScripts(am, sm)
    -->CreateParser() //创建解析器
        -->//添加 rc 文件的解析组件 service、on、import
        parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, GetSubcontext(), std::nullopt));
        parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
        parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
            -->//解析 rc 文件
            parser.ParseConfig("/system/etc/init/hw/init.rc");
                -->ParserConfigDir-->ParserConfigFile
                -->ParserConfigFile
                    -->ParserData


5、While(true) 循环监听
 

auto pending_functions = epoll.Wait(epoll_timeout);


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

                
启动 Service 的过程

/system/core/rootdir/init.rc
    -->
    on nonencrypted
    class_start main --> do_class_start(const BuiltinArguments& args)
    class_start late_start

/system/core/init/builtins.cpp
    -->do_class_start(const BuiltinArguments& args)
        -->StartIfNotDisabled()
    
/system/core/init/service.cpp
    -->StartIfNotDisabled()
        -->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 触发时机

on late-init
    -->trigger zygote-start

on zygote-start
    -->start zygote

Dir:/system/core/init/init.cpp
if (bootmode == "charger") {
        am.QueueEventTrigger("charger");
} else {
    am.QueueEventTrigger("late-init");
}

附: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】

if (strcmp(arg, "--zygote") == 0) {
    zygote = true;
    niceName = ZYGOTE_NICE_NAME;
}
if (zygote) {
    runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}

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

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

startVm() -- 创建虚拟机
startReg() -- 注册 JNI
    --> register_jni_procs(gRegJNI, NELEM(gRegJNI), env) //gRegJNI 是一个 jni 数组对象

env->CallStaticVoidMethod(startClass, startMeth, strArray);  //startClass 即传入的ZygoteInit

//接下来就会执行 ZygoteInit.java 的 main 方法,从 native 层进入 java 层

//JVM :虚拟机,其实就是一块代码,负责实现内存管理,因为是 zygote 通过 fork 创建的进程,所以每个进程都拥有一个独立的 JVM

3、Zygote 的 java 启动

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

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

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

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

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

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

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
zygoteServer = new ZygoteServer(isPrimaryZygote);
    -->
    //frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
        -->
        //frameworks/base/core/java/com/android/internal/os/Zygote.java
        return new LocalServerSocket(fd);

 

(4)创建 SystemServer 进程

Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

ZygoteInit.java--forkSystemServer()
    -->Zygote.java--nativeForkSystemServer()
        -->com_android_internal_os_Zygote_nativeForkSystemServer.cpp【通过 JNI 的映射】
            -->pid_t pid = zygote::ForkCommon(env, true,fds_to_close,fds_to_ignore,true);
                -->pid_t pid = fork();  //最终调用 linux 的 fork()

(5)循环等待

caller = zygoteServer.runSelectLoop(abiList);


四、SystemServer 启动流程

1、参数处理

//ZygoteInit.java
//在 handleSystemServerProcess() 中进行 server 的初始化工作

if (pid == 0) {
    if (hasSecondZygote(abiList)) {
        waitForSecondaryZygote(socketName);
    }
    
    zygoteServer.closeServerSocket();
    return handleSystemServerProcess(parsedArgs);
}

//(1) prepareSystemServerProfile(systemServerClasspath);
//(2) 判断fork args 中是否有 invokWith 参数,如果有则进行WrapperInit.execApplication

if (parsedArgs.mInvokeWith != null) {

    String[] args = parsedArgs.mRemainingArgs;
    // If we have a non-null system server class path, we'll have to duplicate the
    // existing arguments and append the classpath to it. ART will handle the classpath
    // correctly when we exec a new process.
    if (systemServerClasspath != null) {
        String[] amendedArgs = new String[args.length + 2];
        amendedArgs[0] = "-cp";
        amendedArgs[1] = systemServerClasspath;
        System.arraycopy(args, 0, amendedArgs, 2, args.length);
        args = amendedArgs;
    }

    WrapperInit.execApplication(parsedArgs.mInvokeWith,
        parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
        VMRuntime.getCurrentInstructionSet(), null, args);

    throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");

} else {
    ClassLoader cl = getOrCreateSystemServerClassLoader();
    if (cl != null) {
        Thread.currentThread().setContextClassLoader(cl);
    }

    /*
    * Pass the remaining arguments to SystemServer.
    */
    return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
        parsedArgs.mDisabledCompatChanges,
        parsedArgs.mRemainingArgs, cl);
}

2、初始化

(1) ZygoteInit

//ZygoteInit.java

ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);
    -->
    ZygoteInit.nativeZygoteInit();
        --> 
        //JNI
        com_android_internal_os_ZygoteInit_nativeZygoteInit
            -->
            //AndroidRuntime.cpp
            gCurRuntime->onZygoteInit();
                -->
                //app_main.cpp
                virtual void onZygoteInit(){
                    sp<ProcessState> proc = ProcessState::self();
                    ALOGV("App process: starting thread pool.\n");
                    //启动一个 Binder 线程池,用于 SystemServer 和其他线程的通信
                    proc->startThreadPool();
                }

(2)applicationInit

//ZygoteInit.java

return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);
    -->
    //RuntimeInit.java
    return findStaticMain(args.startClass, args.startArgs, classLoader);
        -->
        //RuntimeInit.java; 通过反射找到SystemServer 的 main 方法
        m = cl.getMethod("main", new Class[] { String[].class });
        return new MethodAndArgsCaller(m, argv);
        //耗时操作通过线程完成,MethodAndArgsCaller 的 run 方法中执行 
        mMethod.invoke(null, new Object[] {null, new Object[]{ mArgs });
            -->
            //SystemServer 的 main 方法执行:
            public static void main(String[] args) {
                new SystemServer().run();
            }

五、SystemServer 执行流程

1、初始化

(1)一些属性的设置

(2)初始化上下文

// Initialize the system context.
createSystemContext();

private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

2、创建 SystemServiceManager

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

3、启动一系列系统服务

try {
    t.traceBegin("StartServices");
    startBootstrapServices(t);
    startCoreServices(t);
    startOtherServices(t);
    startApexServices(t);
} catch (Throwable ex) {
    Slog.e("System", "******************************************");
    Slog.e("System", "************ Failure starting system services", ex);
    throw ex;
} finally {
    t.traceEnd(); // StartServices
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高钙小新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值