zoukankan      html  css  js  c++  java
  • 安卓系统启动过程

    韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com

    android启动图示

    ====

    当你按下电源开关后Android设备执行了以下步骤。

    Android启动流程/过程
    此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader

    ====

    第一步:启动电源以及系统启动

    当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。

    第二步:引导程序

    引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redbootubootqi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。

    引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。

    Android引导程序可以在ootableootloaderlegacyusbloader找到。
    传统的加载器包含的个文件,需要在这里说明:

    1. init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
    2. main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签。

    更多关于Android引导程序的可以在这里了解。

    第三步:内核

    Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。

    第四步:init进程

    init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。

    • init进程可以在/system/core/init找到。
    • init.rc文件可以在/system/core/rootdir/init.rc找到。
    • readme.txt可以在/system/core/init/readme.txt找到。

    对于init.rc文件,Android中有特定的格式以及规则。在Android中,我们叫做Android初始化语言。
    Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。
    Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
    语法

    Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
    语法

    Options(选项)
    选项是对服务的描述。它们影响init进程如何以及何时启动服务。
    咱们来看看默认的init.rc文件。这里我只列出了主要的事件以及服务。
    Table

    Action/Service 描述
    on early-init 设置init进程以及它创建的子进程的优先级,设置init进程的安全环境
    on init 设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点
    on fs 挂载mtd分区
    on post-fs 改变系统目录的访问权限
    on post-fs-data 改变/data目录以及它的子目录的访问权限
    on boot 基本网络的初始化,内存管理等等
    service servicemanager 启动系统管理器管理所有的本地服务,比如位置、音频、Shared preference等等…
    service zygote 启动zygote作为应用进程

    在这个阶段你可以在设备的屏幕上看到“Android”logo了。

    第五步

    在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。

    Zygote加载进程

    1. 加载ZygoteInit类,源代码:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    2. registerZygoteSocket()为zygote命令连接注册一个服务器套接字。
    3. preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在<Android Source>/frameworks/base找到“preloaded-classes”文件。
    4. preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载。

    在这个阶段,你可以看到启动动画。

    第六步:系统服务或服务

    完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。

    Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。

    核心服务:

    1. 启动电源管理器;
    2. 创建Activity管理器;
    3. 启动电话注册;
    4. 启动包管理器;
    5. 设置Activity管理服务为系统进程;
    6. 启动上下文管理器;
    7. 启动系统Context Providers;
    8. 启动电池服务;
    9. 启动定时管理器;
    10. 启动传感服务;
    11. 启动窗口管理器;
    12. 启动蓝牙服务;
    13. 启动挂载服务。

    其他服务:

    1. 启动状态栏服务;
    2. 启动硬件服务;
    3. 启动网络状态服务;
    4. 启动网络连接服务;
    5. 启动通知管理器;
    6. 启动设备存储监视服务;
    7. 启动定位管理器;
    8. 启动搜索服务;
    9. 启动剪切板服务;
    10. 启动登记服务;
    11. 启动壁纸服务;
    12. 启动音频服务;
    13. 启动耳机监听;
    14. 启动AdbSettingsObserver(处理adb命令)。

    第七步:引导完成

    一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。

    ========

    Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。

    启动的过程如下图所示

        image

    Android系统启动过程 

    =========

    Android的启动过程可以分为两个阶段,第一阶段是Linux的启动,第二阶段才是Android的启动,下面我们分别来了解一下具体的过程。

    首先是Linux启动,这一部分我想就可以略过了,无非是Linux的Bootloader,Kernel,Driver之类的,在这里唯一要提到 的就是ServiceManager,即服务管理器,这个是做为一个进程在Android加载之前就被启动了,我们可以从init.rc中看到这个配置 项:

    service servicemanager /system/bin/servicemanager

    ServiceManager是Binder的服务管理守护进程,是Binder的核心,由其使用Binder驱动进行IPC管理,关于IPC通讯 的机制,此处不再详述。在APP和Framework中,应用程序使用的ServiceManager.java就是通过Proxy与这个守护进程进行的 通讯。

    然后是Android的启动,接下来要详细描述的部分。我们还是先看一下init.rc中的配置

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

    即linux启动以后,启动zygote服务进程,这个进程恰如其名:孵化器,是所有Android应用程序的孵化器。

    我们来看一下app_process的代码,位置是在:

    frameworks/base/cmds/app_process/app_main.cpp

    在main()函数中有如下代码:

            if (0 == strcmp("--zygote", arg)) {
                bool startSystemServer = (i < argc) ?
     
                        strcmp(argv[i], "--start-system-server") == 0 : false;
     
                setArgv0(argv0, "zygote");
                set_process_name("zygote");
                runtime.start("com.android.internal.os.ZygoteInit",
                    startSystemServer);
     
            }

    从中可以追踪到AndroidRuntime,代码位于:

    frameworks/base/core/jni/AndroidRuntime.cpp

    在start()函数中有如下代码:

        /* start the virtual machine */
        if (startVm(&mJavaVM, &env) != 0)
            goto bail;
             ……
         env->CallStaticVoidMethod(startClass, startMeth, strArray);

    即先启动了虚拟机,然后利用JNI调用了zygoteInit函数。

    继续追踪到frameworks/base/core/java/com/android/internal/os/ZygoteInit.java的main()函数,代码如下:

        if (argv[1].equals("true")) {
    	startSystemServer();
        } else if (!argv[1].equals("false")) {
    	throw new RuntimeException(argv[0] + USAGE_STRING);
        }
    
        Log.i(TAG, "Accepting command socket connections");
    
        if (ZYGOTE_FORK_MODE) {
    	runForkMode();
        } else {
    	runSelectLoopMode();
        }

    前一部分是在启动系统服务,后一部分是虽然是一个条件判断,但ZYGOTE_FORK_MODE被赋了false,所以进行else分支的 runSelectLoopMode()函数,在该函数中,实际上是在一死循环中利用zygoteConnection类通过socket的方式进行消息 处理,用于fork出新的zygote,从而以最轻量级的方式实现每个进程一个虚拟机的机制。

    继续来看startSystemServer(),代码位于:

    frameworks/base/services/java/com/android/server/systemserver.java

    在其main()函数中调用了init1(args)这个native函数,利用JNI机制,跟踪至

    frameworks/base/services/jni/com_android_server_systemService.cpp,然后到

    frameworks/base/cmds/system_server/library/system_init.cpp

    在system_init()函数中有如下代码

        if (strcmp(propBuf, "1") == 0) {
            // Start the SurfaceFlinger
            SurfaceFlinger::instantiate();
        }
     
        AndroidRuntime* runtime = AndroidRuntime::getRuntime();
     
        LOGI("System server: starting Android services./n");
     
        runtime->callStatic("com/android/server/SystemServer", "init2");

    即完成了SurfaceFlinger的实例化,然后利用运行时的callStatic()函数调用了SystemServer的init2()函数,这个函数位于:

    frameworks/base/services/java/com/android/server/SystemServer.java

    代码是:

    public static final void init2() {
            Slog.i(TAG, "Entered the Android system server!");
            Thread thr = new ServerThread();
            thr.setName("android.server.ServerThread");
            thr.start();
    }

    在这个ServerThread线程中,可以看到我们熟悉的Android服务了,比如WallpaperService服务的启动:

    try {
    	Slog.i(TAG, "Wallpaper Service");
    	wallpaper = new WallpaperManagerService(context);
    	ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
    } catch (Throwable e) {
    	Slog.e(TAG, "Failure starting Wallpaper Service", e);
    }

    最后,调用各服务的systemReady()函数通知系统就绪。

    至此,系统的启动过程结束

    从这里可以看出,linux的init在启动若干守护进程之后,就启动了Android的runtime和zygote,zygote再启动虚拟机,系统 服务,系统服务再启动完本地服务后,又启动了若干Android服务,并完成向ServiceManager的注册工作,最后系统启动完成。系统的进程空 间如下图所示:

    可见,由zygote孵化器为各进程以写时复制的方式用最小的代价实现了虚拟机。

    至此,系统的启动过程结束,借用两张图来说明问题:

    从这里可以看出,linux的init在启动若干守护进程之后,就启动了Android的runtime和zygote,zygote再启动虚拟机,系统服务,系统服务再启动完本地服务后,又启动了若干Android服务,并完成向ServiceManager的注册工作,最后系统启动完成。系统的进程空间如下图所示:

    可见,由zygote孵化器为各进程以写时复制的方式用最小的代价实现了虚拟机。

    =======

  • 相关阅读:
    Log4j2 配置
    Spring + SpringMVC配置
    Tomcat 动态数据库连接池
    MySQL数据库备份命令
    一条insert语句插入数据库
    tomcat 性能优化
    linux RPM manager
    mysql 多主
    ceph学习
    python常用程序算法
  • 原文地址:https://www.cnblogs.com/yue31313/p/7397262.html
Copyright © 2011-2022 走看看