Android系统启动流程深度解析:从Bootloader到Zygote的完整旅程

📅 发布时间:2026/7/6 16:13:20 👁️ 浏览次数:
Android系统启动流程深度解析:从Bootloader到Zygote的完整旅程
引言每次按下电源键,你的Android设备经历了什么?从一片黑屏到看到开机Logo,从显示"Android"字样到进入锁屏界面,这短短几秒钟(或十几秒钟)背后,是一场精心编排的"启动大戏"。这场大戏有四幕:第一幕: Bootloader → 加载并启动Kernel 第二幕: Kernel → 初始化硬件,启动init进程(PID 1) 第三幕: init → 挂载文件系统,启动核心服务 第四幕: Zygote → 准备应用运行环境本文将带你完整走完这段旅程,重点聚焦第二幕到第三幕——从Kernel启动init,到init启动Zygote之前的所有准备工作。📖系列前置阅读:建议先阅读第9-11篇(Binder IPC系列),理解进程间通信机制,这是理解系统服务启动的基础。Android启动流程全景图在深入细节之前,先建立整体认知:图:Android 15系统启动的4个阶段,从Bootloader到Zygote的完整旅程,总耗时约6.5秒本文聚焦范围:从Kernel启动init到Zygote启动之前,即上图中的第3步:init进程。Bootloader与Kernel启动(概览)虽然不是本文重点,但理解这两个阶段有助于建立完整认知。Bootloader阶段Bootloader(引导加载程序)是设备上电后执行的第一段代码,由芯片厂商或设备厂商提供。主要任务:硬件初始化:CPU频率和电压配置内存初始化(DDR)外设初始化(Flash/eMMC/UFS)加载Kernel:从boot分区读取Kernel镜像(boot.img)解压Kernel到内存读取Device Tree Blob(DTB,设备树)安全验证:Verified Boot(Android Verified Boot):验证Kernel签名如果验证失败,显示警告或拒绝启动启动Kernel:设置Kernel启动参数(cmdline)跳转到Kernel入口地址(通常是0x80008000)常见Bootloader:LK(Little Kernel):Qualcomm芯片常用U-Boot:开源,通用性强UEFI:PC和部分高端设备关键日志(通过串口或fastboot查看):[0.000000] Booting Linux on physical CPU 0x0 [0.000000] Linux version 5.15.123-android15 (build@hostname) ...Kernel启动阶段Linux Kernel负责硬件抽象和资源管理。主要任务:内存管理初始化:页表设置内存分配器(SLAB/SLUB)初始化进程调度器初始化:CFS调度器(Completely Fair Scheduler)实时调度器(RT)驱动初始化:加载内置驱动(built-in)初始化设备树(Device Tree)中定义的硬件文件系统初始化:挂载rootfs(根文件系统,通常是ramdisk)挂载/system、/vendor等分区(由init负责)创建init进程:// kernel/init/main.c (简化)staticint__refkernel_init(void*unused){// ...if(!ramdisk_execute_command)ramdisk_execute_command="/init";returnrun_init_process(ramdisk_execute_command);}关键Kernel参数(cmdline):# 查看Kernel启动参数adb shellcat/proc/cmdline# 输出示例:# androidboot.hardware=qcom# androidboot.selinux=permissive # 或 enforcing# androidboot.verifiedbootstate=green# init=/system/bin/initinit进程:Android的"创世神"init进程是Android用户态的第一个进程(PID 1),它的职责是创建整个用户态环境。init的三阶段启动Android 15的init分为三个阶段,每个阶段有独立的入口函数:main() → FirstStageMain() → SetupSelinux() → SecondStageMain() ↓ ↓ ↓ ↓ 入口 第一阶段 SELinux设置 第二阶段(核心)让我们分析Android 15的源码:阶段判断逻辑// system/core/init/main.cpp (Android 15)intmain(intargc,char**argv){// 提升优先级(后续会恢复)setpriority(PRIO_PROCESS,0,-20);// 如果argv[0]是"ueventd",则以ueventd模式启动if(!strcmp(basename(argv[0]),"ueventd")){returnueventd_main(argc,argv);}if(argc1){// 子上下文模式(用于隔离某些操作)if(!strcmp(argv[1],"subcontext")){returnSubcontextMain(argc,argv,GetBuiltinFunctionMap());}// SELinux设置阶段if(!strcmp(argv[1],"selinux_setup")){returnSetupSelinux(argv);}// 第二阶段if(!strcmp(argv[1],"second_stage")){returnSecondStageMain(argc,argv);}}// 默认进入第一阶段returnFirstStageMain(argc,argv);}关键设计:init通过命令行参数判断当前应执行哪个阶段每个阶段完成后,会通过execv()重新执行自己,进入下一阶段这种设计允许在SELinux加载后"重启"进程,获得新的安全上下文第一阶段:FirstStageMain()核心目标:创建最基础的文件系统,加载SELinux策略。// system/core/init/first_stage_init.cpp (简化)intFirstStageMain(intargc,char**argv){// ========== 1. 挂载基础文件系统 ==========CHECKCALL(mount("tmpfs","/dev","tmpfs",MS_NOSUID,"mode=0755"));CHECKCALL(mkdir("/dev/pts",0755));CHECKCALL(mkdir("/dev/socket",0755));CHECKCALL(mount("devpts","/dev/pts","devpts",0,NULL));// 挂载proc文件系统(读取内核信息)CHECKCALL(mount("proc","/proc","proc",0,"hidepid=2,gid=3009"));// 挂载sysfs(设备和驱动信息)CHECKCALL(mount("sysfs","/sys","sysfs",0,NULL));// 挂载selinuxfs(SELinux策略文件系统)CHECKCALL(mount("selinuxfs","/sys/fs/selinux","selinuxfs",0,NULL));// ========== 2. 创建必要的设备节点 ==========CHECK