一、整体概览:Android系统架构分层与启动流程

各位同学,今天我们来聊聊Android启动流程的“全景图”。

说实话,我刚开始接触Android底层时,也被这复杂的启动链条搞得头晕。但后来我发现,只要抓住一条主线——从硬件到软件,从底层到上层——整个流程就清晰了。

1.1 Android系统架构分层

先看一张我手绘的架构分层图(你可以在脑中想象):

+------------------------------------------+
|           应用层 (Applications)            |
|   (电话、短信、浏览器、第三方App...)       |
+------------------------------------------+
|         应用框架层 (Application Framework) |
|   (ActivityManager、WindowManager...)      |
+------------------------------------------+
|        系统运行库层 (Android Runtime)      |
|   (ART、Core Libraries)                    |
+------------------------------------------+
|         硬件抽象层 (HAL)                   |
|   (Camera HAL、Audio HAL...)               |
+------------------------------------------+
|          Linux内核层 (Linux Kernel)        |
|   (进程管理、内存管理、驱动...)             |
+------------------------------------------+
|           硬件层 (Hardware)                |
|   (CPU、RAM、Flash、外设...)               |
+------------------------------------------+

这个分层结构,说白了就是“各司其职”。

  • 硬件层:物理基础,CPU、内存、存储芯片都在这里。
  • Linux内核层:这是Android的“心脏”。我习惯把它看作一个超级管家,管理进程、内存、文件系统,还要驱动所有硬件。
  • 硬件抽象层(HAL):一个巧妙的“中间人”。它让上层应用不用关心底层硬件是谁家的。
  • 系统运行库层:ART虚拟机、核心C/C++库都在这里。嗯,这里要注意,ART负责把字节码编译成机器码。
  • 应用框架层:开发者最熟悉的一层。Activity、Service、ContentProvider这些组件都在这里。
  • 应用层:我们每天用的App。
  • 核心观点:Android不是纯粹的Linux,但它离不开Linux内核。没有内核,Android就是一堆代码而已。

    1.2 启动流程的四个阶段

    Android的启动,就像一场接力赛。四个阶段环环相扣:

    阶段 主要任务 时间窗口(典型值)
    Boot ROM 固化在芯片中的代码,加载Bootloader 几十毫秒
    Bootloader 初始化硬件,加载内核到内存 几百毫秒
    Kernel 初始化内核子系统,挂载根文件系统 1-3秒
    Android系统 启动init进程,加载Zygote、SystemServer 5-15秒

    你想想看,从按下电源键到看到桌面,这十几秒里发生了多少事?

    第一阶段:Boot ROM

    这是芯片出厂时就写死的代码。你改不了它,它也不会变。

    它的任务很简单:找到并验证Bootloader。我记得在某个项目中,客户要求实现安全启动,Boot ROM会检查Bootloader的数字签名。如果签名不对,直接死机——这就是所谓的“安全启动链”。

    避坑指南:我曾经遇到过一台设备,刷机后变砖。后来发现是Boot ROM找不到Bootloader了。原因?Bootloader被意外擦除了。所以,永远不要动Boot ROM区域,除非你清楚自己在做什么。

    第二阶段:Bootloader

    Bootloader是“承上启下”的角色。它负责:

    • 初始化CPU、内存、时钟等基础硬件
    • 从存储介质(eMMC、UFS)中读取内核镜像
    • 把内核加载到内存指定位置
    • 跳转到内核入口点

    我个人习惯把Bootloader分成两个阶段:

    1. 第一阶段(SPL/MLO):极简代码,初始化DDR内存。因为Boot ROM太小,放不下复杂逻辑。
    2. 第二阶段(U-Boot/LK):完整的引导程序,支持文件系统、网络、命令行。

    为什么会这样设计?说白了,就是“先活下来,再谈发展”。

    第三阶段:Kernel

    这是Linux内核的“主场”。内核启动时,会做以下几件大事:

    • 架构初始化:设置页表、中断向量、时钟系统
    • 内存管理初始化:建立伙伴系统、slab分配器
    • 进程调度器初始化:创建init进程(PID=1)
    • 驱动加载:根据设备树(DTB)匹配并初始化驱动
    • 挂载根文件系统:通常是ramdisk或system分区

    嗯,这里要注意:内核启动的最后一步,是执行根文件系统中的init程序。这个init,就是Android世界的“第一个进程”。

    警告:内核启动过程中,如果某个关键驱动加载失败(比如存储驱动),系统会直接panic。我曾经调试过一个bug,设备总是在内核启动到一半时重启。最后发现是eMMC驱动时序有问题。所以,驱动稳定性是内核启动的命门

    第四阶段:Android系统

    内核启动完成后,控制权交给了init进程。Android系统的启动,从这里正式开始:

    1. init进程:解析init.rc脚本,启动关键服务(ueventd、servicemanager)
    2. Zygote进程:Android的“孵化器”。它预加载了所有Java核心类库,然后监听socket请求,fork出新的应用进程。
    3. SystemServer:Zygote fork出的第一个Java进程。它负责启动所有系统服务(ActivityManager、PackageManager、WindowManager等)。
    4. Launcher:桌面应用。当SystemServer启动完成后,会发送一个“BOOT_COMPLETED”广播,Launcher收到后显示桌面。

    你想想看,从init到Launcher,这中间有多少个进程在接力?

    1.3 Linux内核在其中的核心角色

    Linux内核在Android启动中扮演了三个关键角色:

    角色 具体职责 我的理解
    硬件抽象层 通过驱动管理所有硬件资源 没有内核驱动,CPU、内存、屏幕都是摆设
    进程调度器 决定哪个进程先运行、运行多久 Android的“时间管理者”
    内存管理者 分配和回收物理内存 Low Memory Killer就是基于内核的OOM机制

    我个人觉得,内核最重要的贡献是提供了稳定的运行环境。Android上层可以频繁更新,但内核一旦稳定,很少改动。我在项目中见过一些团队,为了“优化性能”乱改内核调度参数,结果系统反而更卡了。嗯,内核这东西,能不碰就别碰

    总结一下:Android启动流程,本质上是“从硬件到软件”的层层唤醒。Boot ROM唤醒Bootloader,Bootloader唤醒Kernel,Kernel唤醒init,init唤醒Android世界。而Linux内核,就是这个链条上最核心的一环——它既是硬件的管理者,也是软件的基石。

    下一章,我们会深入Boot ROM的细节,看看芯片上电后到底发生了什么。到时候我会分享一个我在调试“冷启动时序”时踩过的坑,很有意思。