Android的开机启动流程概述

前言

做Android开发已经有些时日了,一直想系统而深入的去了解Android的启动流程。前前后后花费了很大的功夫去查阅和研究,所以想把微薄的成果记录下来,留做日后回顾。顺便呢,也分享给大家。必定会有很多的疏漏和谬误,欢迎大家在评论区补充和指正。当然,文中不免会有一些摘抄引用,如有侵权,可以联系本人处理。


Android的开机启动流程概述

我相信,只要接触过Android的人,都会看过下面这张图。

Android层次架构图

(图片来源于网络,侵权请联系我!)

图片清晰地展示了Android的五层架构,从上到下依次是:应用层,应用框架层,库层,运行时层以及Linux内核层。而Android的启动流程是自下而上的,大体上分为三个阶段:1. BootLoader引导;2. 启动Kernel;3. 启动Android。如果再细化一点,则如下图所示:

Android的启动流程图

(图片来源于网络,侵权请联系我!)

接下来我来稍微具体的描述一下这个过程。


Step 1. Boot Rom

当长按开机键的时候,引导芯片开始从固化在ROM的预设代码开始执行。然后加载引导程序到RAM。


Step 2. BootLoader

BootLoader,又称为引导程序。它是在操作系统运行之前运行的一段程序,是运行的第一个程序。主要有检查RAM,初始化硬件参数等功能,当然它的最终目的是把操作系统给拉起来。

文件路径: /bootable/bootloader/legacy/

BootLoader的主要功能分析,我摘抄过来,一起看看:

其实Bootloader主要的必须的作用只有一个:就是把操作系统映像文件拷贝到RAM中去,然后跳转到它的入口处去执行,我们称之为启动加载模式,该过程没有用户的介入,是它正常工作的模式。它的步骤如下:

Stage1:

  1. 硬件设备初始化。为stage2的执行及随后内核的执行准备好基本的硬件环境

  2. 为加载stage2 准备ram空间。为了获得更好的执行速度,通常吧stage2加载到ram中执行

  3. 复制stage2的代码到ram中

  4. 设置好堆栈

  5. 跳转到stage2的c程序入口

Stage2:

  1. 初始化本阶段要使用的硬件设备

  2. 检测系统内存映射

  3. 将内核映像和根文件系统映像从flash读到ram中

  4. 为内核设置启动参数

  5. 调用内核

(摘自:http://www.cnblogs.com/little221/archive/2012/12/06/2804387.html


Step 3. 初始化Kernel

接着就进入C语言编写的结构无关的代码了。这个入口的函数是start_kernel函数。start_kernel 函数完成了内核的大部分初始化工作。实际上,可以将start_kernel 函数看做内核的main函数。start_kernel函数执行到最后调用了reset_init函数进行后续的初始化。 reset_init函数最主要的任务就是启动内核线程kernel_initkernel_init函数将完成设备驱动程序的初始化,并调用init_post函数启动用户空间的init进程。到init_post函数为止,内核的初始化已经基本完成。

文件路径:/kernel_imx/init/main.c


Step 4. init进程

当初始化内核之后,就会启动一个相当重要的祖先进程,也就是init进程,在Linux中所有的进程都是由init进程直接或间接fork出来的。init进程负责创建系统中最关键的几个子进程,尤其是zygote。另外,它还提供了property service(属性服务),类似于windows系统的注册表服务。

在Android系统中,会有个init.rc脚本。init进程一启动就会读取并解析这个脚本文件,把其中的元素整理成自己的数据结构(链表)。

文件路径:
/system/core/init/init.c
/system/core/rootdir/init.rc
/system/core/init/readme.txt


Step 5. Zygote进程

init进程创建之后,会fork出一个Zygote进程,这个进程是所有Java进程的父进程。我们知道,Linux是基于C的,而Android是基于Java的(当然底层也是C)。所以这里就会fork出一个Zygote Java进程用来fork出其他的进程。在zygote开启的时候,会调用ZygoteInit.main()进行初始化。下面我们看一段ZygoteInit.main()源码:

public static void main(String argv[]) {

......

    // 加载zygote的时候,会传入参数,startSystemServer变为true
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = 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)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

......

         // 启动的SystemServer进程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }
......
}

文件路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java


Step 6. SystemServer进程

前面ZygoteInit.java里面通过startSystemServer()fork出了SystemServer进程,这个进程在整个的Android中非常重要,它和Zygote进程 一样,是Android Framework层的两大重要进程。系统里面重要的服务都是在这个进程里面开启的,例如AMS, WindowsManager, PackageManagerService等等都是由这个SystemServerfork出来的。在下面SystemServer 的代码中可以看到,这些服务如何开启和具体开启了哪些服务。

public final class SystemServer {


    // The main entry point from zygote.
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }

    private void run() {

......

        // 初始化原生服务库
        System.loadLibrary("android_servers");
        nativeInit();

        // 初始化系统上下文
        createSystemContext();

        // 创建SystemServiceManager对象
        mSystemServiceManager = new SystemServiceManager(mSystemContext);

        // 开启服务
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }
        
        ......

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    //初始化系统上下文对象mSystemContext,并设置默认的主题。
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

    //在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。
    private void startBootstrapServices() {
    
......
    
        //初始化ActivityManagerService
        mActivityManagerService = mSystemServiceManager
              .startService(ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

        //初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化
        mPowerManagerService = mSystemServiceManager
              .startService(PowerManagerService.class);

        // 现在电源管理已经开启,ActivityManagerService负责电源管理功能
        mActivityManagerService.initPowerManagement();

        // 开启DisplayManagerService
        mDisplayManagerService = mSystemServiceManager
              .startService(DisplayManagerService.class);

        // 开启PackageManagerService
        mPackageManagerService = PackageManagerService.main(mSystemContext,mInstaller,
              mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

......
    }

    private void startCoreServices() {...}// 启动一些基本服务。
    
    private void startOtherServices() {...}// 启动其他服务。
}

文件路径:/frameworks/base/services/java/com/android/server/SystemServer.java

从上面SystemServer 代码中可以看出,在SystemServer进程开启的时候,就会初始化ActivityManagerService 。同时,会加载本地系统的服务库,调用createSystemContext()创建系统上下文,创建ActivityThread及开启各种服务等等。


Step 7. Home Activity

上面ActivityManagerService 开启之后,会调用finishBooting() ,完成引导过程。同时发送开机广播“ACTION_BOOT_COMPLETED”


final void finishBooting() {

......
    final int userId = mStartedUsers.keyAt(i);
    Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
    intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
    intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
    broadcastIntentLocked(...);
......

}

文件路径:/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

之后就会开启系统的主程序——Launcher程序,完成系统界面的加载与显示。

至此,Android的开机启动流程大概就完成了。


参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容