Android系统启动流程(基于Android 11)

Android系统启动流程(基于Android 11)

Android小彩虹2021-08-15 23:38:07200A+A-

应用进程的虚拟机实例是何时创建的?进程的Binder线程池又是何时启动?为什么所有的应用进程都是由Zygote进程创建?其实这些问题的答案都藏在Android系统的启动流程中。这部分作为整个系统的开端,里面有很多知识点是我们广大Android开发者进阶所必须要了解的。本文将基于Android 11的代码简单的梳理一下这部分流程。

1. init进程启动

Android系统是基于Linux kernel内核的。当用户长按电源键后,会引导芯片加载BootLoader到内存中,并开始拉起Linux kernel内核。待Linux kernel启动完成后便会启动第一个用户空间的进程——init进程。启动init进程时,会进入system/core/init/main.cpp文件执行main方法,主要分两个阶段初始化完成启动过程,代码如下:

/*system/core/init/main.cpp*/
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif
    // Boost prio which will be restored later
    setpriority(PRIO_PROCESS, 0, -20);
    if (!strcmp(basename(argv[0]), "ueventd")) {
        // init进程创建子进程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")) {
            // 启动Selinux安全策略
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            // 执行第二阶段启动
            return SecondStageMain(argc, argv);
        }
    }
    // 执行第一阶段启动
    return FirstStageMain(argc, argv);
}
  • 先执行FirstStageMain(argc, argv);FirstStageMain()中主要做了一些目录创建、设备节点创建和设备挂载的动作。简化代码如下:
int FirstStageMain(int argc, char** argv) {
    ...
    CHECKCALL(clearenv());
    CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
    // Get the basic filesystem setup we need put together in the initramdisk
    // on / and then we'll let the rc file figure out the rest.
    CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755")); // 挂载tmpfs文件系统
    CHECKCALL(mkdir("/dev/pts", 0755));
    CHECKCALL(mkdir("/dev/socket", 0755));// 创建dev/socket设备节点
    CHECKCALL(mkdir("/dev/dm-user", 0755));
    CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));// 挂载devpts文件系统
    ...
    CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));// 挂载sysfs文件系统
    CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
    CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));// 提前创建了kmsg设备节点文件,用于输出log信息
    ...
#undef CHECKCALL
    ...

    return 1;
}
  • 再执行SecondStageMain(argc, argv):主要逻辑是启动属性服务、解析init.rc文件并启动相关进程,简化代码如下:
/*system/core/init/init.cpp*/
int SecondStageMain(int argc, char** argv) {
    ...
    PropertyInit(); // 1.初始化属性系统,并从指定文件读取属性
    ...
    StartPropertyService(&property_fd);// 2.设置其他系统属性并开启系统属性服务
    ...
    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();
    LoadBootScripts(am, sm);// 3.解析init.rc等文件,建立rc文件的action 、service,启动其他进程
    ...
    return 0;
}

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()) {
        /* 依次解析不同路径下谷歌system、soc厂商vendor、odm厂商的init.rc文件并启动相关进程 */
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        parser.ParseConfig("/system_ext/etc/init");
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

加载解析rc文件并启动服务。init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language),编写的脚本 init.rc文件是在init进程启动后执行的启动脚本,文件中记录着init进程需执行的操作。init.rc主要包含五种类型语句:

  • Action
  • Command
  • Service
  • Option
  • Import

下面我们继续看看init.rc中是如何定义启动zygote进程的?

2. Zygote进程启动

首先在init.rc里改成了通过${ro.zygote}属性的值来决定引入Zygote相关的配置,如下所示:

/*system/core/rootdir/init.rc*/
import /system/etc/init/hw/init.${ro.zygote}.rc
...
on late-init
    # Now we can start zygote for devices with file based encryption
    trigger zygote-start // 1. 触发启动zygote
...
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
    wait_for_prop odsign.verification.done 1
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start statsd
    start netd
    start zygote // 2.启动zygote服务
    start zygote_secondary
...

${ro.zygote}的取值有4种,在init.rc的同级目录system/core/rootdir/下,可以看到4个Zygote相关的配置文件,表示系统所支持程序的bit位数:

  1. init.zygote32.rc,Zygote进程的执行程序路径为/system/bin/app_process
  2. init.zygote64.rc,Zygote进程的执行程序路径为/system/bin/app_process64
  3. init.zygote32_64.rc,会启动两个Zygote进程,有两个执行程序,32为主模式
  4. init.zygote64_32.rc,会启动两个Zygote进程,有两个执行程序,64为主模式(系统兼容运行64位和32位的应用)

我们看看目前最新项目设备中普遍使用的init.zygote64_32.rc文件写法:

/*system/core/rootdir/init.zygote64_32.rc*/
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote //启动64位的zygote
    class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system //创建一个名为zygotesocket 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 task_profiles ProcessCapacityHigh MaxPerformance critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload //启动32位的zygote
    class main priority -20 user root group root readproc reserved_disk socket zygote_secondary stream 660 root system socket usap_pool_secondary stream 660 root system onrestart restart zygote task_profiles ProcessCapacityHigh MaxPerformance 

第一行中,service表示Zygote进程以服务的形式来启动zygote则是进程的名字,/system/bin/app_process64是执行程序的路径,后面几项则是传给执行程序的参数,其中--start-system-server表示在Zygote进程启动后需要启动system_server进程。然后是Zygote进程是使用socket来进行跨进程通信的,所以会创建一个名为zygote的socket,660表示访问权限rw-rw----,表示文件拥有者和同一群组用户具有读写权限。

init进程启动后,通过fork和execv来启动Zygote进程,如下简化代码所示:

/*system/core/init/service.cpp*/
Result<void> Service::Start() {
    ...
    pid_t pid = -1;
    if (namespaces_.flags) {
        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
    } else {
        pid = fork();// 1.fork创建service进程(也就是zygote进程)
    }
    if (pid == 0) {
        ...
        if (!ExpandArgsAndExecv(args_, sigstop_)) {
            PLOG(ERROR) << "cannot execv('" << args_[0]
                        << "'). See the 'Debugging init' section of init's README.md for tips";
        }
        ...
    }
}

static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
    std::vector<std::string> expanded_args;
    std::vector<char*> c_strings;
    expanded_args.resize(args.size());
    c_strings.push_back(const_cast<char*>(args[0].data()));
    for (std::size_t i = 1; i < args.size(); ++i) {
        auto expanded_arg = ExpandProps(args[i]);
        if (!expanded_arg.ok()) {
            LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
        }
        expanded_args[i] = *expanded_arg;
        c_strings.push_back(expanded_args[i].data()); // 封装参数
    }
    c_strings.push_back(nullptr);
    if (sigstop) {
        kill(getpid(), SIGSTOP);
    }
    // 2. c_strings[0]是执行程序路径,即如果启动的是zygote服务时,execve会运行/system/bin/app_process64
    return execv(c_strings[0], c_strings.data()) == 0;
}

2.1 native层app_process

首先运行可执行程序app_process的入口main函数:

/*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;
    ...
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true; // 参数标识启动zygote进程
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true; //参数标识启动system_server进程
        } 
        ...
    }
    ...
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */); // 进程名app_process修改为zygote
    }
    if (zygote) {
        // 启动Zygote,执行AndroidRuntime.start函数
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        ...
    }
}

我们进一步来看AndroidRuntime的start流程代码:

/*frameworks/base/core/jni/AndroidRuntime.cpp*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());
    ...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {// 1.启动VM虚拟机
        return;
    }
    onVmCreated(env);

    /* * Register android functions. */
    if (startReg(env) < 0) { // 2.注册框架JNI调用到虚拟机中
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        // 3.JNI调用进入java层执行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);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            ...
    }
    ...
}

从代码中可以看到AndroidRuntime#start方法中主要完成三件事情

  1. 启动进程的VM虚拟机;

  2. 注册Android系统框架JNI调用到虚拟机中;

  3. 通过JNI调用进入java层执行ZygoteInit的main函数

2.2 java层ZyogeInit

我们继续往下看简化的代码流程:

 /*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
 public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
        ...
        try {
            ...
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    // 在init.rc文件中,有--start-system-server参数,表示要创建SystemServer
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                }
                ...
            }
            ...
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                ...
                preload(bootTimingsTraceLog);// 1.预加载资源
                ...
            }
            ...
            zygoteServer = new ZygoteServer(isPrimaryZygote); // 2.创建Socket服务端
            if (startSystemServer) {
                // 3.fork启动system_server进程
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                ...
            }
            //4. sokcet服务端等待AMS请求(AMS会通过socket请求Zygote来创建应用程序进程)
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } 
        ...
    }

  static void preload(TimingsTraceLog bootTimingsTraceLog) {
        ...
        preloadClasses();// 1.加载system/etc/preloaded-classes文件中定义的各个系统类
        ...
        preloadResources(); // 2.加载系统中定义的各个drawables、color资源
        ...
    }

从代码中可以看到ZygoteInit#main方法中主要fork启动system_server进程:

  1. zygote进程中预加载类、主题资源、字体资源等,基于linux的copy-on-write机制,从而加速后续zygote fork创建出的应用进程的启动速度

  2. 创建socket服务端,用于跨进程通信;

  3. fork创建启动系统system_server进程;

  4. Sokcet服务端进入循环监听等待,等待后续AMS请求(AMS会通过socket请求Zygote来创建应用程序进程)。

3. system_server进程的启动

我们接着ZygoteInit#forkSystemServer往下看:

/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
        ...
        /* Hardcoded command line to start the system server */
        // 1.构建启动system_server进程的相关设置参数
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                // system_server启动的类名
                "com.android.server.SystemServer",
        };
        ...
        try {
            ...
            /* Request to fork the system server process */
            // 2.fork创建system_server进程,具体实现在native层
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            // 3.pid为0代表在新创建的system_server进程中,继续通过handleSystemServerProcess进一步处理
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
    
     /** * Finish remaining work for the newly forked system server process. */
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        ...
        if (parsedArgs.mInvokeWith != null) {
            ...
        } else {
           ...
            /* * Pass the remaining arguments to SystemServer. */
            // 调用ZygoteInit#zygoteInit函数具体处理
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }
    }
    
     public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) {
        ...
        // 1.RuntimeInit初始化,通过setDefaultUncaughtExceptionHandler设置默认的异常处理机制
        RuntimeInit.commonInit();
        // 2.触发启动进程的Binder线程池
        ZygoteInit.nativeZygoteInit();
        // 3.内部经过层层调用,最终通过反射创建"com.android.server.SystemServer"类对象并执行其main函数
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

继续结合代码看看RuntimeInit#applicationInit是如何实现反射创建"com.android.server.SystemServer"类对象并执行其main函数的:

/*frameworks/base/core/java/com/android/internal/os/RuntimeInit.java*/
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) {
        ...
        return findStaticMain(args.startClass, args.startArgs, classLoader);
}

protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
        Class<?> cl;

        try {
            // 1.通过反射加载构建"com.android.server.SystemServer"类对象
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            //2.访问获取"com.android.server.SystemServer"的main方法
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        ...
        /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */
        // 3.通过抛异常触发执行main函数并清除调用栈
        return new MethodAndArgsCaller(m, argv);
    }
    
    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                // 通过反射调用main函数
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

从上面的分析中可以看到,system_server进程创建后,会通过反射创建"com.android.server.SystemServer"入口类对象并执行其main方法,我们继续往下看代码简化流程:

/*frameworks/base/services/java/com/android/server/SystemServer.java*/
public static void main(String[] args) {
        new SystemServer().run();
}

private void run() {
   ...
    // 1.创建主线程Looper
    Looper.prepareMainLooper();
    // 2.创建系统Context上下文
    createSystemContext();
    // 3.创建SystemServiceManager,用于后续系统服务(AMS、WMS等)的创建、启动和生命周期管理
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    // 4.服务根据优先级被分成3批来启动:
    try {
        t.traceBegin("StartServices");
        //启动引导服务,如AMS、PMS等
        startBootstrapServices(t);
        //启动核心服务
        startCoreServices(t);
         //启动其他服务
        startOtherServices(t);
     } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
     } finally {
        t.traceEnd(); // StartServices
     }
     // 5.开启looper循环
     Looper.loop();
}

总结一下上述流程,system_server进程创建之后,主要做了如下几件事情

  1. 启动进程的Binder线程池;

  2. 创建SystemServiceManager大管家,用于后续系统服务(AMS、WMS等)的创建、启动和生命周期管理;

  3. 用SystemServiceManager按照优先级启动系统各个服务;

  4. 创建并启动进程的主线程的loop循环;

4. Launcher应用的启动

我们接上一节system_server进程创建之后启动系统服务的流程往下看,以AMS服务的启动为例,相关简化代码流程如下:

/*frameworks/base/services/java/com/android/server/SystemServer.java*/
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        ...
        t.traceBegin("StartActivityManager");
        // 1.SystemServiceManager启动AMS服务
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();
        t.traceEnd();
        ...
}

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
     ...
    // We now tell the activity manager it is okay to run third party
    // code. It will call back into us once it has gotten to the state
    // where third party code can really run (but before it has actually
    // started launching the initial applications), for us to complete our
    // initialization.
    // 2.从这里开始便可以开始启动三方APP应用(如Launcher)
     mActivityManagerService.systemReady(() -> {
            ...
        }, t);
}

从上面的代码流程中可以看到system_server进程创建之后,启动系统各核心服务的最后会调用到mActivityManagerService#systemReady便可正式开始启动三方APP应用(如Launcher),我们继续往下看:

/*frameworks/base/services/java/com/android/server/am/ActivitymanagerService.java*/
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t){
     ...
     if (bootingSystemUser) {
        t.traceBegin("startHomeOnAllDisplays");
        // 由于Android系统支持多用户和多显示,调用startHomeOnAllDisplays启动每个display上的Home Activity
        mAtmInternal.startHomeOnAllDisplays(currentUserId,"systemReady");
        t.traceEnd();
     }
}

startHomeOnAllDisplays中经过层层调用最终会调用到startHomeActivity启动Category类型为CATEGORY_HOME类型的应用,也就是Launcher桌面,相关代码简化流程如下:

/*frameworks/base/services/java/com/android/server/wm/RootWindowContainer.java*/
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, boolean allowinstrumenting, boolean fromHomeKey){
     ...
     // 最终调用startHomeActivity启动Category类型为CATEGORY_HOME类型的应用,也就是Launcher桌面
     mService.startActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);
     return true;
}

5.调试建议

假如你的手机遇到开机比较慢的问题,我们该如何去定位问题的原因出在哪儿呢?这里提供几点调试建议:

5.1 基于系统log定位问题

重启手机,在开机时使用如下adb命令抓取相关日志:

adb shell "logcat -b events |grep "boot_p""

06-03 09:43:19.554   730   730 I boot_progress_start: 4274 //标志着系统kernel启动完成,第一个用户空间进程init进程启动,耗时4274ms
06-03 09:43:19.768   730   730 I boot_progress_preload_start: 4487 //标志着zygote进程开始preload预加载资源
06-03 09:43:20.669   730   730 I boot_progress_preload_end: 5389 //标志着zygote进程preload预加载资源完成
06-03 09:43:21.082  1196  1196 I boot_progress_system_run: 5802 // 标志着system_server进程启动
06-03 09:43:22.186  1196  1196 I boot_progress_pms_start: 6905 // 标志着系统pkms服务启动并开始扫描已安装应用的动作
06-03 09:43:22.430  1196  1196 I boot_progress_pms_system_scan_start: 7150
06-03 09:43:22.757  1196  1196 I boot_progress_pms_data_scan_start: 7477
06-03 09:43:23.033  1196  1196 I boot_progress_pms_scan_end: 7753
06-03 09:43:23.185  1196  1196 I boot_progress_pms_ready: 7905// // 标志着系统pkms服务扫描完成
06-03 09:43:24.133  1196  1196 I boot_progress_ams_ready: 8853 // 标志着AMS已经进入systemReady状态可以启动Home Activity
06-03 09:43:25.468  1196  1523 I boot_progress_enable_screen: 10187 // 标志着锁频界面已经点亮显示,整个开机完成,耗时10187ms

5.2 使用bootchart性能分析工具定位问题

bootchart是一个用于linux启动过程性能分析的开源工具软件,在系统启动过程中自动收集CPU占用率、磁盘吞吐率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。Android 系统源码中有bootchart的实现,路径在system/core/init/bootchart.cpp。具体使用方法可以参考下文进行操作: blog.csdn.net/qq_19923217…

6. 总结

最后还是用一张图总结Android系统的启动核心流程:

Android系统开机启动流程.png

7. 参考文章

图解 | Android系统的启动 juejin.cn/post/688478…

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们