说说Android系统的启动流程

Posted canbot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了说说Android系统的启动流程相关的知识,希望对你有一定的参考价值。

android系统的启动流程

Android系统的启动流程可以分三部分来分析,
Android系统有哪些主要的系统进程?
这些系统进程是怎么启动的?
启动之后都做了什么事?

首先看下图,分三个阶段介绍Android系统的启动流程:

第一阶段:Android设备上电后,首先会从处理器芯片上ROM的启动引导代码开始执行,芯片上ROM会寻找Bootloader代码,并加载到内存。(这一步由“芯片厂商”负责设计和实现)

第二阶段:Bootloader开始执行,首先负责完成硬件的初始化,然后找到Linux内核代码,并加载到内存。(这一步由“设备厂商”负责设计和实现)

第三阶段:Linux内核开始启动,初始化各种软硬件环境,加载驱动程序,挂载根文件系统,并执行init程序,由此开启Android的世界。(这一步则是Android内核开发过程中需要涉及的地方)

Android系统以及各大Linux的发行版,他们的Linux内核部分启动过程都是差不多的,他们之间最大的区别就在于init程序的不同,因为init程序决定了系统在启动过程中,究竟会启动哪些守护进程和服务,以及呈现出怎样的一个用户UI界面。

因此,init程序是分析Android启动过程中最核心的程序。
对应的代码位于:system/core/init/init.c,
init程序最核心的工作主要有三点:

(1) 创建和挂载一些系统目录/设备节点,设置权限,如:/dev, /proc, and /sys。

(2) 解析 init.rc 和 init..rc,并启动属性服务,以及一系列的服务和进程。

(3) 显示boot logo,默认是“Android”字样。

其中,最重要的步骤是第二步,一系列的Android服务在这时被启动起来,其实Android系统的启动最重要的过程也就是各个系统服务的启动,因为系统所有的功能都是依赖这些服务来完成的,比如启动应用程序,拨打电话,使用WIFI或者蓝牙,播放音视频等等,只要这些服务都能正常地启动起来并且正常工作,整个Android系统也就完成了自己的启动。

这些服务包含两部分,一部分是本地服务,另一部分是Android系统服务,所有的这些服务都会向ServiceManager进程注册,由它统一管理,这些服务的启动过程介绍如下:

(1)本地服务

本地服务是指运行在C++层的系统守护进程,一部分本地服务是init进程直接启动的,它们定义在init.rc脚本和init..rc中,如 ueventd、servicemanager、debuggerd、rild、mediaserver等。还有一部分本地服务,是由这些本地服务进一步创建的,如mediaserver服务会启动AudioFlinger, MediaPlayerService, 以及 CameraService 等本地服务。

我们可以通过查看init.rc和init..rc文件找出具体有哪些本地服务被init进程直接启动了,这些文件的位置:system/core/rootdir/ 或者在各服务模块的根目录下,其在rc脚本文件的配置如下:

service zygote /system/bin/app_process
service servicemanager /system/bin/servicemanager
service surfacelinger /system/bin/surfaceflinger
service media /system/bin/mediaserver

注意,每一个由init直接启动的本地服务都是一个独立的Linux进程,在系统启动以后,我们通过adb shell ps命令,可以查看所有进程信息。

(2)Android的系统服务

Android的系统服务是指运行在Dalvik虚拟机进程中的服务,这些服务的创建过程描述如下:

init进程会执行app_process程序,创建Zygote进程,它是Android系统最重要的进程,所有后续的Android应用程序都是由它fork出来的。

Zygote进程会首先fork出"SystemServer"进程,"SystemServer"进程的全部任务就是将所有的Android核心服务启动起来,这些服务包括:

当所有的服务都启动完毕后,SystemServer会打印出“Making services ready”,然后通过ActivityManager启动Home界面,并发送“ACTION_BOOT_COMPLETED”广播消息。

注意,这些Android的系统服务并没有各自运行在独立的进程中,它们由SystemServer以线程的方式创建,所以都运行在同一个进程中,即SystemServer进程中。

(3)详细分析Zygote进程和SystemServer进程的启动

Zygote的启动流程:

init进程fork出zyogte进程

启动虚拟机,注册jni函数,为进入java层做准备

预加载系统资源,如系统主题资源,类等

启动system server,非常重要,里面跑了很多系统服务

进入socket Loop,不断接受socket消息并处理

zygote工作流程:

启动的最后,进入了socket loop循环,有消息进入runOnce()函数,如下:

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller 
    String[] args = readArgumentList(); //读取参数列表
    int pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);; //根据参数启动子进程
    
    if(pid == 0)
        //in child
        handleChildProc(args, ...); 
        //在子进程里面干活,其实执行的就是java类得main函数(入口函数),java类名来自上面读取的参数列表。
        //参数列表是AMS跨进程发过来的,类名就是ActivityThread.main(),
        //也就是说,应用程序进程执行后会马上执行ActivityThread.main()函数
        return true;
    

system_server的启动流程:

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException 
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_PTRACE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Containers run without this capability, so avoid setting it in that case */
        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) 
            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
        
        /* Hardcoded command line to start the system server */
        String args[] = 
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        ;
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try 
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
                    //创建system_server进程,zygote fork出来
         catch (IllegalArgumentException ex) 
            throw new RuntimeException(ex);
        

        /* For child process */
        if (pid == 0) 
            if (hasSecondZygote(abiList)) 
                waitForSecondaryZygote(socketName);
            
			//子进程,走进system_server启动的具体逻辑了
            handleSystemServerProcess(parsedArgs);
        

        return true;
    
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller 

        closeServerSocket();

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) 
            Process.setArgV0(parsedArgs.niceName);
        

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) 
            performSystemServerDexOpt(systemServerClasspath);
        

        if (parsedArgs.invokeWith != null) 
            String[] args = parsedArgs.remainingArgs;
            // 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(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
            

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
         else 
            ClassLoader cl = null;
            if (systemServerClasspath != null) 
                cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            

            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        

        /* should never reach here */
    

RuntimeInit中的zygoteInit:

//初始化分三步
 public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller 
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();

        commonInit();//通用化初始化
        nativeZygoteInit();//jni调用底层app_main.cpp中的onZygoteInit方法
        applicationInit(targetSdkVersion, argv, classLoader);
    

	//nativeZygoteInit(),这里启动了binder机制,binder线程,因为system_server里很多系统服务需要和其他进程通信
	//如跟应用进程通讯,或者和service manager进程通信
	virtual void onZygoteInit()
	    sp<ProcessState> proc = ProcessState::self();
	    proc->startThreadPool();
	
 
    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller 
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args;
        try 
            args = new Arguments(argv);
         catch (IllegalArgumentException ex) 
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
        //调用java类的入口函数,就是system server的java类
    
 
 
	//SystemServer的类的main函数
	public static void main(String[] args)
	   new SystemServer().run();  //new了一个SystemServer对象,执行了它的run函数
	


	private void run()
	    Looper.prepareMainLooper(); //为主线程创建Looper
	    
	    System.loadLibrary("android_servers"); //加载共享库,就是system server里的系统服务的native 层的代码,都在共享库
	    createSystemContext(); //创建系统上下文,system server可以看成是应用进程,因为它也有context,application,Activity thread
		//系统服务分3批次,分别启动    
	    startBootstrapServices();
	    startCoreServices();
	    startOtherServices();
	    
	    //不管这个loop是不是真的在处理消息,但这个主线程不可以退出,主线程退出进程就退出了
	    Looper.loop();
	

(4)问题思考

1. 系统服务怎么发布?

//就是系统服务把binder注册到ServiceManager里面,统一管理
void publishBinderService(String name, IBinder service)
    publishBinderService(name, service, false);

 
void publishBinderService(String name, IBinder service,...)
    ServiceManager.addService(name, service, allowlsolated);

2. 系统服务跑在什么线程?

有的系统服务有自己的工作线程,例如AMS、PMS 等。

还有大家共用的工作线程:DisplayThread, FgTHread, IoThread, UiThread。

DisplayThread是显示用的

FgThread是前台任务

IoThread是Io任务

UiThread是Ui显示的,UiThread并不是主线程,而是一个子线程,所以说明UI的刷新不必一定在主线程,子线程也行。

这些工作线程系统服务都会跑,当然还有binder线程,因为应用跨进程调过来肯定先在binder线程里面。

3. 为什么系统服务不都跑在binder线程?

binder线程是大家一起共享的,如果系统负载很重,binder线程池忙碌,可能影响系统服务响应的实时性,另外如果任务太耗时,长时间占用binder线程也不妥。

4. 为什么系统服务不都跑在自己私有的工作线程?

不可能每个服务都启动一个工作线程,一共上百个系统服务,线程开太多了会内存溢出的。而且太多线程之间切换对性能不利。

5. 跑在binder线程和跑在工作线程,如何取舍?

总的来说,对于实时性要求不那么高,并且处理起来不太耗时的任务可以就放在binder线程里。另外启动工作线程也可以避免同步的问题,因为应用程序跨进程调用过来是在binder线程池,通过切到工作线程可以让binder调用序列化,不用到处上锁。

6. 怎么解决系统服务启动的互相依赖?

例如system_server进程里,系统服务有上百个,解决复杂的依赖关系并不容易:

1)分批次启动,基础的先启动,例如AMS PMS PKMS,很多service都依赖于他们所以要先启动。

2)分阶段启动,通知已启动的service到了什么阶段,哪些资源可以用了,这些service就可以做这个阶段可以做的初始化了。

7. 桌面的启动

AMS服务就绪时会调用systemReady函数,里面会启动桌面:

public void systemReady(final Runnable goingCallback)
    ...
    startHomeActivityLocked(mCurrentUserId, "systemReady");
    ...

桌面可以看成单独的系统级应用,这里只启动了桌面的Activity,Activity的onCreate里面会启动LoaderTask:

mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
//loaderTask会向packageManagerService查询所有当前已经安装的应用,把图标显示到桌面上,点击图标,就会启动应用的LauncherActivity
mPm.queryIntentActivitiesAsUser

以上是关于说说Android系统的启动流程的主要内容,如果未能解决你的问题,请参考以下文章

关于Android系统的启动流程

Android App安装以及启动流程

Activity的启动流程

Android 深入系统完全讲解

Android Framework 启动流程必知必会

Android 10.0 Activity的启动流程