Android系统启动

0 阅读8分钟

Android是一种基于Linux的开发源代码软件栈,为各类设备和机型而创建。可以参考谷歌官方的介绍。下图为参考官方原图而绘制的Android软件堆栈图

Android系统启动

Android 系统启动流程是什么?

  1. Powon上电后,CPU读取ROM中固定的地址,开始加载Bootloader到RAM中,然后执行Bootloader。

  2. Bootloader:芯片生产后就烧录好的,主要是初始化外设(网络、内存等)、引导Kernel启动,设置启动参数。

  3. Kernel:

    1. 初始化硬件设置、挂载根文件系统
    2. 加载驱动程序
    3. 寻找init文件,启动init进程
  4. Android系统初始化过程:

    1. 挂载分区、创建目录,比如/dev, /proc等
    2. 动态加载驱动
    3. 启动系统服务:servicemanager、adbd、surfaceflingerzygote......
    4. 配置环境变量
    5. 守护系统

优化Android系统的启动时间,从Uboot、Kernel、和Android系统初始化这三个过程进行优化。根据log分析出比较耗时的过程。

Android启动模式

  1. recovery升级模式:启动recovery分区内核和文件系统。
  2. 正常启动模式:引导内核和启动Android系统。

流程图.jpg

Init守护进程

Init进程是Linux内核启动完成后在用户空间启动的第一个进程(pid=1),主要负责初始化工作,启动属性服务,解析init.rc并启动Zygoter进程(Java进程的祖先),同时也会创建Binder服务大管家(servicemanager进程)。

init进程的作用:

  1. 解析并运行所有的init.rc文件
  2. 会创建目录、挂载分区,生成设备驱动节点。
  3. 初始化和启动属性服务

init进程main

  1. init进程源码文件位置system/core/init/init.cpp
  2. init系统中位置 /init

内核启动后,会调用system/core/init/目录下的main.cpp中的main()函数,main函数中可以看出有5个重要的阶段,且都是单独执行的,分别是

  1. ueventd_main:init 进程创建子进程uevented,负责设备节点的创建、权限设定等一系列工作
  2. SubcontextMain : 初始化日志系统
  3. SetupSelinux : 启动Selinux安全策略
  4. SecondStageMain : 位于init.cpp中,用来启动init.rc脚本
  5. FirstStageMain : 负责设置加载系统其余部分的最低要求。具体来说就是挂载/dev,/proc 以及将system.img挂载移动到有ramdisk的设备的/下。
// system/core/init/main.cpp
using namespace android::init;

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#elif __has_feature(hwaddress_sanitizer)
    __hwasan_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 进程创建子进程uevented,负责设备节点的创建、权限设定等一系列工作
        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);
}

SecondStageMain

SecondStageMain()方法在init.cpp

//system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {
    //在设置了REBOOT_BOOTLOADER_ON_PANIC参数后,将会捕获所有init和内核崩溃的信号,方便开发时进行处理。非开发版本一般关闭。
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }
    
    boot_clock::time_point start_time = boot_clock::now(); //记录启动的时间

    trigger_shutdown = [](const std::string& command) { shutdown_state.TriggerShutdown(command); };

    SetStdioToDevNull(argv); //将stin/stdou/stderr全部重定向到/dev/null/
    InitKernelLogging(argv); //初始化内核日志,失败时转储堆栈信息
    LOG(INFO) << "init second stage started!";
    ....
    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();

    LoadBootScripts (am, sm);  //加载init.rc脚本
    ...
    return 0;
}

LoadBootScripts

从ro.boot.init_rc属性中找到init.rc脚本并加载,如果没有则加载下边相关的init.rc文件。最后通过ActionManager和ServiceList执行启动相关服务。

// system/core/init/init.cpp
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()) {
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        // late_import is available only in Q and earlier release. As we don't
        // have system_ext in those versions, skip late_import for system_ext.
        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);
    }
}

Zygote进程

Zygote进程是一个进程孵化器,负责创建虚拟机实例、应用程序进程、系统服务进程SystemServer。他通过fork的方式创建子进程,子进程能继承父进程的系统资源,例如常用类、注册的JNI函数、共享库等。

暂时无法在飞书文档外展示此内容

Init.rc脚本

Android8.0对init.rc文件进行了拆分,比如64位的Zygote的启动脚本在init.zygote64.rc文件中。

Init.rc有Android Init Language (AIL)编写,由5大类语句组成:操作Actions、命令Commands、服务Services、选项Options和导入Imports。

init.rc里通过${ro.zygote}属性的值来决定引入Zygote相关的配置,这里有四种取值,在/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.zygote64_32.rc:会启动两个Zygote,64位为主模式。
 #/system/core/rootdir/init.rc import /init.environ.rc
import /system/etc/init/hw/init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /system/etc/init/hw/init.usb.configfs.rc
import / system /etc/init/hw/init.${ro.zygote}.rc
# Cgroups are mounted right before early-init using list from /etc/cgroups.json
on early-init
    # Disable sysrq from keyboard
    write /proc/sys/kernel/sysrq 0

    # Android doesn't need kernel module autoloading, and it causes SELinux
    # denials.  So disable it by setting modprobe to the empty string.  Note: to
    # explicitly set a sysctl to an empty string, a trailing newline is needed.
    write /proc/sys/kernel/modprobe \n

    # Set the security context of /adb_keys if present.
    restorecon /adb_keys
    ......
    
  

init.zygote64.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server

  1. service表示Zygote进程以服务的形式来启动,
  2. Zygote 进程的名字
  3. /system/bin/app_process64是执行程序的路径
  4. --start-system-server表示zygote启动后需要启动SystemServer进程。

socket zygote stream 660 root system

  1. zygote进程通过socket来进行跨进程通信,会创建一个名为zygote的socket,660表示权限是rw-rw---。
 #/system/core/rootdir/init.zygote64.rc  service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main    //伴随着 main class启动而启动
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system   //创建socket, 名字是zygote
    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        //当zygote重启时,则会重启media
    onrestart restart media.tuner
    onrestart restart netd       //当zygote重启时,则会重启netd
    onrestart restart wificond
    task_profiles ProcessCapacityHigh
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

app_process64

init启动后通过fork和execve来启动Zygoter进程

然后执行app_process64中的main函数用来启动Java虚拟机

 #frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[])
{
    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append(""");
        argv_String.append(argv[i]);
        argv_String.append("" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.string()); 
    }

    AppRuntime runtime (argv[ 0 ], computeArgBlockSize(argc, argv))  ;  //创建AppRuntime对象
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++; 
    
   
        }
    }
    .........................

 if (zygote) {  //使用runtime.start启动Zygote进程
 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.");
    }
}

AndroidRuntime#start

  1. 启动Java virtual machine
  2. 为JVM注册JNI方法
  3. 根据传入的com.android.internal.os.ZygoteInit,通过JNI调用其main方法
 #frameworks/ base/core/jni/AndroidRuntime.cpp:1193

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

    /*
     * Register android functions.
     * /
      //JNI方法注册   if ( startReg (env) < 0 ) {  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);
        /* 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 {
  //startClass = com.android.internal.os.ZygoteInit 
            //startMeth = main  env-> CallStaticVoidMethod (startClass, startMeth, strArray); 

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    .........
}

ZygoteInit#main

com.android.internal.os.ZygoteInit#main

public static void main(String[] argv) {
    .............................
        boolean startSystemServer = false; //是否创建SystemServer
        String zygoteSocketName = "zygote"; //默认的socket名字
        String abiList = null;
        boolean enableLazyPreload = false; //是否延迟加载资源
        //在init.zygote64.rc  是否有start-system-server         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)) {
                //init.rc可以通过--socket-name=指定socket名字来覆盖默认值                 zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException("Unknown command line argument: " + argv[i]);
            }
        }

        ...........
        Zygote.initNativeState(isPrimaryZygote);

        ZygoteHooks.stopZygoteNoThreadCreation();
        
  //创建一个ZygoteServer
 zygoteServer = new ZygoteServer (isPrimaryZygote); 
  //启动SystemServer,fork一个SystemServer进程,并开始运行。 
        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

            // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
            // child (system_server) process.
            if (r != null) {
                r.run();
                return;
            }
        }
        / /等待AMS请求,AMS会通过socket请求Zygote创建应用程序。 
        // The select loop returns early in the child process after a fork and
        // loops forever in the zygote.
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with fatal exception", ex);
        throw ex;
    } finally {
        if (zygoteServer != null) {
            zygoteServer.closeServerSocket();
        }
    }

}

SytemServer进程

  1. 创建looper:Looper.prepareMainLooper();
  2. 初始化native service:加载动态库libandroid_servers.so
  3. 创建上下文:createSystemContext();
  4. 创建SystemServerManager,用于服务的创建,启动和生命周期管理。
  5. 启动引导服务:startBootstrapServices,例如AMS、PMS,ATMS
  6. 启动核心服务:startCoreServices
  7. 启动其他服务:startOtherServices,例如WMS
  8. 开启loop循环:Looper.loop();

startBootstrapServices

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ......
    // Activity manager runs the show.
    t.traceBegin("StartActivityManager");
    // TODO: Might need to move after migration to WM.
    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();
    
    .......
    t.traceBegin("StartPowerManager");
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    t.traceEnd();
    
    ......
    // Display manager is needed to provide display metrics before package manager
    // starts up.
    t.traceBegin("StartDisplayManager");
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    t.traceEnd();
    
    ......
    t.traceBegin("StartPackageManagerService");
    try {
        Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
        mPackageManagerService = PackageManagerService.main(
                mSystemContext, installer, domainVerificationService,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF);
    } finally {
        Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
    }

    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    t.traceEnd();    
}

startCoreServices

startOtherServices

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    t.traceBegin("startOtherServices");
    
    t.traceBegin("StartWindowManagerService");
    // WMS needs sensor service ready
    mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
            new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
            DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
                    | DUMP_FLAG_PROTO);
    t.traceEnd();  
    
    t.traceBegin("SetWindowManagerService");
    mActivityManagerService.setWindowManager(wm);
    t.traceEnd();

    t.traceBegin("WindowManagerServiceOnInitReady");
    wm.onInitReady();
    t.traceEnd();  
    
    t.traceBegin("StartSystemUI");
    try {
        startSystemUi(context, windowManagerF); 
    } catch (Throwable e) {
        reportWtf("starting System UI", e);
    }
    t.traceEnd();
}