编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

    • 库的解读

    • 专栏博客

      • 系统启动Zygote
        • 一、引言:按下电源键之后发生了什么
        • 二、BootLoader与Linux内核启动
          • 2.1 硬件上电与BootLoader
          • 2.2 boot.img的结构
          • 2.3 Linux内核的初始化
          • 2.4 Android内核与标准Linux的差异
        • 三、Init进程:Android世界的开端
          • 3.1 Init进程的角色
          • 3.2 Init进程源码分析
          • 3.3 属性服务的实现原理
        • 四、Init.rc解析与服务启动
          • 4.1 init.rc的语法结构
          • 4.2 Zygote服务的声明
          • 4.3 服务启动的触发机制
        • 五、Zygote进程的诞生
          • 5.1 从app_process到ZygoteInit
          • 5.2 app_process的源码分析
          • 5.3 虚拟机的创建过程
          • 5.4 ZygoteInit.main()的核心逻辑
        • 六、Zygote的Fork机制
          • 6.1 为什么使用Fork而不是New
          • 6.2 Copy-On-Write(COW)原理
          • 6.3 Fork过程的源码分析
          • 6.4 USAP(Unspecialized App Process)池
        • 七、SystemServer的启动流程
          • 7.1 SystemServer的Fork
          • 7.2 SystemServer.main()的核心逻辑
          • 7.3 服务启动的三个阶段
          • 7.4 服务启动的依赖关系
        • 八、系统服务的注册与启动
          • 8.1 ServiceManager的角色
          • 8.2 系统服务的注册过程
          • 8.3 SystemServiceManager的生命周期管理
        • 九、Launcher的启动与桌面显示
          • 9.1 AMS启动Launcher的时机
          • 9.2 Launcher的角色与启动流程
          • 9.3 开机广播的发送
        • 十、Application进程的创建过程
          • 10.1 完整的应用启动链路
          • 10.2 AMS请求Zygote的通信过程
          • 10.3 ActivityThread.main():应用的真正入口
        • 十一、预加载机制与启动优化
          • 11.1 Zygote预加载的内容
          • 11.2 预加载的内存效益分析
          • 11.3 预加载类的选择策略
          • 11.4 启动速度优化策略
        • 十二、Android启动中的关键设计思想
          • 12.1 进程隔离与安全模型
          • 12.2 分层启动的设计哲学
          • 12.3 单一职责与服务化
          • 12.4 预加载+COW的"空间换时间"哲学
        • 十三、面试高频问题与深度分析
          • 13.1 Zygote为什么用Socket而不用Binder通信?
          • 13.2 SystemServer为什么不直接启动,而要从Zygote fork?
          • 13.3 Android为什么有两个Zygote(32位和64位)?
          • 13.4 如何观察系统启动过程?
        • 十四、ActivityThread深入分析
          • 14.1 ActivityThread核心流程
          • 14.2 Application启动流程
          • 14.3 Activity启动入口
        • 十五、Context上下文设计
          • 15.1 Context设计目的
          • 15.2 Context类的设计
          • 15.3 Context作用域
        • 十六、组件通信Intent设计
          • 16.1 Intent设计思想
          • 16.2 Bundle与数据传递
          • 16.3 PendingIntent设计
        • 十七、Android硬件抽象层
          • 17.1 HAL层介绍
          • 17.2 HAL层设计
          • 17.3 系统架构分层
      • Binder通信原理
      • Handler消息机制
      • Activity启动原理
      • 四大组件原理分析
      • AMS与组件管理
      • View绑制与渲染
      • 事件分发机制
      • Surface渲染原理
      • 自定义View设计
      • WMS窗口管理
      • PMS与APK安装
      • 虚拟机与类加载
      • 内存管理与GC
      • 线程与并发编程
      • 性能优化与监控
      • 序列化与数据存储
      • 组件化与路由设计
      • 插件化与热修复
      • NDK开发实践
      • WebView核心设计
      • ADB常见使用操作
    • 智能硬件

  • iOS开发和进阶

  • Web开发和进阶

  • Linux应用开发

  • Apps
  • Android提升进阶
  • 专栏博客
杨充
2026-04-14
目录

系统启动Zygote

# 01.系统启动与Zygote

# 目录介绍

  • 一、引言:按下电源键之后发生了什么
  • 二、BootLoader与Linux内核启动
    • 2.1 硬件上电与BootLoader
    • 2.2 boot.img的结构
    • 2.3 Linux内核的初始化
    • 2.4 Android内核与标准Linux的差异
  • 三、Init进程:Android世界的开端
    • 3.1 Init进程的角色
    • 3.2 Init进程源码分析
    • 3.3 属性服务的实现原理
  • 四、Init.rc解析与服务启动
    • 4.1 init.rc的语法结构
    • 4.2 Zygote服务的声明
    • 4.3 服务启动的触发机制
  • 五、Zygote进程的诞生
    • 5.1 从app_process到ZygoteInit
    • 5.2 app_process的源码分析
    • 5.3 虚拟机的创建过程
    • 5.4 ZygoteInit.main()的核心逻辑
  • 六、Zygote的Fork机制
    • 6.1 为什么使用Fork而不是New
    • 6.2 Copy-On-Write(COW)原理
    • 6.3 Fork过程的源码分析
    • 6.4 USAP(Unspecialized App Process)池
  • 七、SystemServer的启动流程
    • 7.1 SystemServer的Fork
    • 7.2 SystemServer.main()的核心逻辑
    • 7.3 服务启动的三个阶段
    • 7.4 服务启动的依赖关系
  • 八、系统服务的注册与启动
    • 8.1 ServiceManager的角色
    • 8.2 系统服务的注册过程
    • 8.3 SystemServiceManager的生命周期管理
  • 九、Launcher的启动与桌面显示
    • 9.1 AMS启动Launcher的时机
    • 9.2 Launcher的角色与启动流程
    • 9.3 开机广播的发送
  • 十、Application进程的创建过程
    • 10.1 完整的应用启动链路
    • 10.2 AMS请求Zygote的通信过程
    • 10.3 ActivityThread.main():应用的真正入口
  • 十一、预加载机制与启动优化
    • 11.1 Zygote预加载的内容
    • 11.2 预加载的内存效益分析
    • 11.3 预加载类的选择策略
    • 11.4 启动速度优化策略
  • 十二、Android启动中的关键设计思想
    • 12.1 进程隔离与安全模型
    • 12.2 分层启动的设计哲学
    • 12.3 单一职责与服务化
    • 12.4 预加载+COW的"空间换时间"哲学
  • 十三、面试高频问题与深度分析
    • 13.1 Zygote为什么用Socket而不用Binder通信?
    • 13.2 SystemServer为什么不直接启动,而要从Zygote fork?
    • 13.3 Android为什么有两个Zygote(32位和64位)?
    • 13.4 如何观察系统启动过程?
  • 十四、ActivityThread深入分析
    • 14.1 ActivityThread核心流程
    • 14.2 Application启动流程
    • 14.3 Activity启动入口
  • 十五、Context上下文设计
    • 15.1 Context设计目的
    • 15.2 Context类的设计
    • 15.3 Context作用域
  • 十六、组件通信Intent设计
    • 16.1 Intent设计思想
    • 16.2 Bundle与数据传递
    • 16.3 PendingIntent设计
  • 十七、Android硬件抽象层
    • 17.1 HAL层介绍
    • 17.2 HAL层设计
    • 17.3 系统架构分层
  • 十八、总结

# 一、引言:按下电源键之后发生了什么

当用户按下Android手机的电源键,到看到桌面图标可以操作,中间经历了一个复杂而精密的启动流程。这个过程涉及硬件初始化、Linux内核加载、Native进程启动、Java虚拟机初始化、系统服务注册等多个阶段。

理解Android系统启动流程,是深入掌握Android底层原理的第一步。它不仅帮助我们理解系统架构的设计思想,更能在实际开发中解决启动优化、系统定制、Framework层修改等高级问题。

疑惑:为什么Android不像桌面Linux那样直接启动应用,而要经过Zygote这样一个"孵化器"进程?

本文将从BootLoader开始,逐层深入,最终揭示Zygote这个Android世界的"母体"是如何工作的。


# 二、BootLoader与Linux内核启动

# 2.1 硬件上电与BootLoader

Android设备的启动从硬件层面开始:

电源键按下
    ↓
CPU从固定地址(ROM)读取第一条指令
    ↓
BootROM代码执行:初始化RAM、加载BootLoader
    ↓
BootLoader执行(如U-Boot/LK)
    ├── 初始化硬件(时钟、内存控制器、存储设备)
    ├── 设置CPU运行模式(从实模式切换到保护模式)
    ├── 加载Linux内核镜像(boot.img)到RAM
    └── 跳转到内核入口地址
1
2
3
4
5
6
7
8
9
10
11

BootLoader是一段运行在操作系统之前的程序,它的核心职责是准备运行环境并加载内核。Android常用的BootLoader包括高通的LK(Little Kernel)和联发科的preloader。

# 2.2 boot.img的结构

Android的boot.img包含Linux内核和ramdisk:

boot.img结构:
┌─────────────────────┐
│   Boot Header       │  ← 包含内核大小、ramdisk大小、加载地址等信息
├─────────────────────┤
│   Kernel (zImage)   │  ← 压缩的Linux内核
├─────────────────────┤
│   Ramdisk           │  ← 初始的根文件系统(包含init程序)
├─────────────────────┤
│   Second Stage      │  ← 可选的第二阶段引导程序
├─────────────────────┤
│   DTB               │  ← 设备树(Device Tree Blob)
└─────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12

# 2.3 Linux内核的初始化

内核被加载到内存后,执行流程如下:

kernel入口(start_kernel)
    ↓
初始化核心子系统
    ├── 内存管理(mm_init)
    ├── 调度器(sched_init)
    ├── 中断(trap_init)
    ├── 定时器(timer_init)
    └── 文件系统(vfs_caches_init)
    ↓
挂载根文件系统
    ↓
启动第一个用户空间进程:/init(PID = 1)
1
2
3
4
5
6
7
8
9
10
11
12

关键点:Linux内核启动完成后,会创建PID为1的init进程,这是整个Android用户空间的"始祖进程"。所有后续的进程(包括Zygote、SystemServer、应用进程)都是init的子孙进程。

# 2.4 Android内核与标准Linux的差异

Android对Linux内核做了若干重要修改:

Android特有的内核组件:
├── Binder驱动    → IPC通信核心(替代传统的System V IPC)
├── Ashmem       → 匿名共享内存(比POSIX shm更灵活,支持引用计数回收)
├── ION/dmabuf   → 统一的内存分配器(用于GPU/Camera等硬件缓冲区共享)
├── Low Memory Killer → 内存不足时按优先级杀进程(比OOM Killer更精细)
├── Wakelocks    → 电源管理(防止CPU休眠)
└── Logger       → Android日志系统(logcat的内核支持)
1
2
3
4
5
6
7

这些修改体现了Android作为移动操作系统的特殊需求:高效的IPC、严格的内存管理、精细的电源控制。


# 三、Init进程:Android世界的开端

# 3.1 Init进程的角色

Init是Android启动后第一个用户空间进程(PID=1),它承担三个核心职责:

Init进程的三大职责:
┌─────────────────────────────────────────────┐
│  1. 解析并执行init.rc配置文件                  │
│     → 创建文件系统目录、设置权限、启动服务       │
├─────────────────────────────────────────────┤
│  2. 属性服务(Property Service)               │
│     → 管理系统属性的读写(类似Windows注册表)     │
├─────────────────────────────────────────────┤
│  3. 子进程管理                                │
│     → 监控子进程退出,必要时重启关键服务          │
└─────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11

# 3.2 Init进程源码分析

Init进程的入口在 system/core/init/main.cpp:

// Android 12+ init进程入口
int main(int argc, char** argv) {
    // 第一阶段:挂载基本文件系统
    if (argc == 1 || strcmp(argv[1], "selinux_setup") == 0) {
        return SetupSelinux(argv);  // SELinux安全策略
    }
    
    if (strcmp(argv[1], "second_stage") == 0) {
        return SecondStageMain(argc, argv);  // 核心逻辑
    }
    
    return FirstStageMain(argc, argv);  // 挂载/dev, /proc, /sys等
}
1
2
3
4
5
6
7
8
9
10
11
12
13

第一阶段(FirstStageMain)的关键工作:

int FirstStageMain(int argc, char** argv) {
    // 1. 创建基本设备节点
    mount("tmpfs", "/dev", "tmpfs", ...);
    mount("proc", "/proc", "proc", ...);
    mount("sysfs", "/sys", "sysfs", ...);
    
    // 2. 创建必要的设备文件
    mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3));
    mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
    
    // 3. 加载SELinux策略,然后重新执行init进入第二阶段
    execv("/init", argv);  // 重新执行自己,进入second_stage
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3.3 属性服务的实现原理

Android的属性系统是一个全局的键值对存储,通过共享内存实现高效读取:

属性服务架构:
┌──────────────────────────────────────┐
│           PropertyService             │
│  ┌─────────────────────────────┐     │
│  │    共享内存区域(mmap)      │     │
│  │  ┌───────┬───────────────┐  │     │
│  │  │ Key   │ Value         │  │     │ ← 所有进程可读(mmap只读映射)
│  │  ├───────┼───────────────┤  │     │
│  │  │ ro.build.type │ userdebug│ │   │
│  │  │ sys.boot_completed │ 1  │  │   │
│  │  └───────┴───────────────┘  │     │
│  └─────────────────────────────┘     │
│  ┌───────────────────────┐           │
│  │  Socket接口(写请求)  │           │ ← 只有init进程处理写操作
│  └───────────────────────┘           │
└──────────────────────────────────────┘

读取路径(快速):进程直接读mmap内存 → O(1),无IPC开销
写入路径(安全):进程 → socket → init进程 → SELinux权限检查 → 写入共享内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

设计思想:读多写少的场景下,用共享内存实现零开销读取,用socket+权限检查保证写入安全。这种"读者无锁、写者串行"的设计在Android系统中非常典型。


# 四、Init.rc解析与服务启动

# 4.1 init.rc的语法结构

init.rc使用Android特有的配置语言(Android Init Language),它由五种类型的语句组成:

init.rc语法结构:
├── Action(动作)
│   on <trigger>          ← 触发条件
│       <command>         ← 要执行的命令
│       <command>
│
├── Service(服务)
│   service <name> <pathname> [<argument>]*
│       <option>          ← 服务选项(用户、组、能力等)
│       <option>
│
├── Import(导入)
│   import <path>         ← 导入其他.rc文件
│
├── Options(选项)
│   class, user, group, oneshot, disabled...
│
└── Commands(命令)
    mkdir, chmod, chown, mount, start, stop...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 4.2 Zygote服务的声明

Zygote在init.rc中的声明(以64位为例):

# /system/etc/init/hw/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

关键参数解读:

/system/bin/app_process64     → Zygote的可执行文件(实际是app_process)
-Xzygote                     → 传递给VM的参数
/system/bin                   → Java类的搜索路径
--zygote                      → 标记以Zygote模式启动
--start-system-server         → 启动后fork出SystemServer
socket zygote stream 660      → 创建Unix域套接字,供AMS请求fork新进程
priority -20                  → 高优先级(nice值-20,最高优先级)
1
2
3
4
5
6
7

# 4.3 服务启动的触发机制

init进程的事件循环:
while (true) {
    1. 解析所有.rc文件,构建Action列表和Service列表
    2. 按触发条件执行Action
       on early-init  → 最早执行的初始化(设置权限、创建挂载点)
       on init        → 基础初始化(创建目录、设置rlimit)
       on late-init   → 触发class_start core/main/hal
       on boot        → 设置系统属性、启动服务
    3. 启动被标记为class=main的服务(包括Zygote)
    4. 进入无限循环,处理子进程退出事件
}
1
2
3
4
5
6
7
8
9
10
11

# 五、Zygote进程的诞生

# 5.1 从app_process到ZygoteInit

Zygote进程的启动入口是 app_process(C++层),最终进入Java层的 ZygoteInit:

启动调用链:
init进程 fork() → app_process64
    ↓
app_process::main()  [frameworks/base/cmds/app_process/app_main.cpp]
    ↓
AndroidRuntime::start("com.android.internal.os.ZygoteInit", ...)
    ↓
startVm()  → 创建Dalvik/ART虚拟机实例
    ↓
startReg() → 注册JNI函数
    ↓
JNI调用 → ZygoteInit.main()  [Java层]
1
2
3
4
5
6
7
8
9
10
11
12

# 5.2 app_process的源码分析

// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]) {
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    
    // 解析参数
    bool zygote = false;
    bool startSystemServer = false;
    
    while (i < argc) {
        if (strcmp(argv[i], "--zygote") == 0) {
            zygote = true;       // Zygote模式
        } else if (strcmp(argv[i], "--start-system-server") == 0) {
            startSystemServer = true;  // 需要启动SystemServer
        }
        i++;
    }
    
    if (zygote) {
        // 启动Zygote:创建虚拟机 → 注册JNI → 调用ZygoteInit.main()
        runtime.start("com.android.internal.os.ZygoteInit", args, /*zygote=*/true);
    } else {
        // 普通应用进程启动
        runtime.start("com.android.internal.os.RuntimeInit", args, /*zygote=*/false);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 5.3 虚拟机的创建过程

// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, ...) {
    // 1. 创建JVM实例
    JNI_CreateJavaVM(&mJavaVM, &env, &initArgs);
    // 此时ART虚拟机已经初始化完成,包括:
    //   - 堆内存分配(默认最大512MB,可调)
    //   - GC线程创建
    //   - JIT编译器初始化
    //   - 类加载器准备
    
    // 2. 注册Android框架的JNI函数
    startReg(env);
    // 注册了大量JNI函数,例如:
    //   - android_os_Binder → Binder的JNI桥接
    //   - android_view_Surface → Surface的JNI桥接
    //   - android_util_Log → Log的JNI桥接
    
    // 3. 通过反射调用Java层的main方法
    jclass startClass = env->FindClass(className);
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 5.4 ZygoteInit.main()的核心逻辑

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String[] argv) {
    ZygoteServer zygoteServer = null;
    
    try {
        // 1. 预加载资源(关键优化点!)
        preload();
        // 包括:预加载常用Java类、预加载Android框架资源(图片、布局等)
        // 预加载共享库(如ICU、OpenGL等)
        
        // 2. 创建Zygote的Socket服务端
        zygoteServer = new ZygoteServer();
        
        // 3. Fork出SystemServer进程
        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
            if (r != null) {
                r.run();  // 子进程(SystemServer)走这里
                return;
            }
        }
        
        // 4. Zygote进入循环,等待AMS的请求来fork新的应用进程
        caller = zygoteServer.runSelectLoop(abiList);
    } finally {
        if (zygoteServer != null) {
            zygoteServer.closeServerSocket();
        }
    }
    
    if (caller != null) {
        caller.run();  // 在fork出的子进程中执行
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 六、Zygote的Fork机制

# 6.1 为什么使用Fork而不是New

疑惑:为什么Android创建新进程使用Linux的fork(),而不是从头创建一个新的虚拟机实例?

答疑:这是Android启动性能优化的核心设计决策。

方案对比:
┌──────────────────────────────────────────────────────┐
│  方案A:每次从头创建进程                               │
│  新建进程 → 初始化VM → 加载核心类 → 加载资源 → 就绪    │
│  耗时:约2-5秒                                        │
├──────────────────────────────────────────────────────┤
│  方案B:Fork Zygote进程(Android采用的方案)            │
│  fork() → COW复制地址空间 → 特化(关闭不需要的资源)     │
│  耗时:约200-500毫秒                                  │
└──────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10

Fork的优势:

  1. 速度快:fork()使用COW(Copy-On-Write),瞬间完成地址空间复制
  2. 内存共享:预加载的类和资源在物理内存中只有一份,所有应用共享
  3. 一致性:所有应用进程从同一个起点出发,保证环境一致

# 6.2 Copy-On-Write(COW)原理

Fork前(Zygote进程):
虚拟页面A → 物理页面X(预加载的类)
虚拟页面B → 物理页面Y(预加载的资源)
虚拟页面C → 物理页面Z(VM堆内存)

Fork后(子进程共享物理内存):
Zygote:  虚拟页面A → 物理页面X [只读标记]
子进程:  虚拟页面A → 物理页面X [只读标记]  ← 共享同一物理页

子进程写入页面A时触发COW:
子进程:  虚拟页面A → 物理页面X'(新分配并拷贝)[可写]
Zygote:  虚拟页面A → 物理页面X [恢复可写]
1
2
3
4
5
6
7
8
9
10
11
12

论证:通过/proc/[pid]/smaps可以观察到实际的内存共享情况:

# 查看某个应用进程的内存映射
adb shell cat /proc/$(pidof com.example.app)/smaps | grep -A 5 "boot.art"

# 典型输出:
# Size:          8192 kB       ← 虚拟内存大小
# Rss:           6144 kB       ← 实际驻留物理内存
# Shared_Clean:  6000 kB       ← 与Zygote共享的只读页面(大部分!)
# Private_Dirty:  144 kB       ← 进程私有的写时复制页面(很少)
1
2
3
4
5
6
7
8

这说明绝大部分预加载的内存页面是与Zygote共享的,COW极大地节省了物理内存。

# 6.3 Fork过程的源码分析

// ZygoteConnection.java → Zygote.java
static int forkAndSpecialize(int uid, int gid, int[] gids,
        int runtimeFlags, int[][] rlimits, ...) {
    
    // 1. Fork前:暂停所有线程(保证fork安全)
    ZygoteHooks.preFork();
    // ART内部:暂停GC线程、暂停编译线程、暂停其他daemon线程
    // 原因:fork()只复制调用线程,多线程fork可能导致死锁
    
    // 2. 执行fork
    int pid = nativeForkAndSpecialize(...);
    // native层调用 fork() 系统调用
    
    // 3. Fork后的处理
    ZygoteHooks.postForkCommon();
    
    if (pid == 0) {
        // 子进程:
        // - 设置进程名、UID/GID
        // - 关闭Zygote的socket(子进程不需要监听)
        // - 重新初始化线程池
        // - 调用应用的入口方法
    }
    
    return pid;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 6.4 USAP(Unspecialized App Process)池

Android 10引入了USAP机制,进一步优化应用启动速度:

传统模式:
AMS请求 → Zygote收到 → fork() → 特化 → 应用就绪
                          ↑ 耗时点

USAP模式:
预先fork一批进程(USAP Pool)
AMS请求 → 从池中取一个USAP → 特化 → 应用就绪
                              ↑ fork开销已提前完成

USAP池管理:
┌──────────────────────────────────────┐
│  USAP Pool(默认保持3-10个预备进程)   │
│  ┌────┐ ┌────┐ ┌────┐ ┌────┐       │
│  │USAP│ │USAP│ │USAP│ │USAP│       │
│  └────┘ └────┘ └────┘ └────┘       │
│  每个USAP已完成fork、VM初始化         │
│  等待被"认领"并特化为具体应用进程       │
└──────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 七、SystemServer的启动流程

# 7.1 SystemServer的Fork

SystemServer是Zygote fork出的第一个也是最重要的子进程:

// ZygoteInit.java
private static Runnable forkSystemServer(...) {
    String[] args = {
        "--setuid=1000",          // system用户
        "--setgid=1000",
        "--setgroups=1001,1002,...",
        "--capabilities=...",      // 系统能力
        "--nice-name=system_server",
        "--runtime-args",
        "--target-sdk-version=10000",
        "com.android.server.SystemServer",  // 入口类
    };
    
    // Fork出SystemServer进程
    pid = Zygote.forkSystemServer(...);
    
    if (pid == 0) {
        // 子进程(SystemServer)
        zygoteServer.closeServerSocket();  // 关闭Zygote的socket
        return handleSystemServerProcess(parsedArgs);
    }
    
    return null;  // 父进程(Zygote)继续
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 7.2 SystemServer.main()的核心逻辑

// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    // 1. 设置系统属性
    SystemProperties.set("persist.sys.dalvik.vm.lib.2", 
                         VMRuntime.getRuntime().vmLibrary());
    
    // 2. 准备主线程Looper
    Looper.prepareMainLooper();
    
    // 3. 加载libandroid_servers.so(系统服务的Native层)
    System.loadLibrary("android_servers");
    
    // 4. 创建SystemServiceManager(服务管理器)
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    
    // 5. 按顺序启动三组服务
    startBootstrapServices();  // 引导服务(AMS、PMS、PowerMS等)
    startCoreServices();       // 核心服务(BatteryService等)
    startOtherServices();      // 其他服务(WindowMS、InputMS等)
    
    // 6. 进入消息循环
    Looper.loop();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 7.3 服务启动的三个阶段

引导服务(Bootstrap Services):系统最核心的服务
├── Installer                    → APK安装相关
├── ActivityTaskManagerService   → Activity任务管理(Android 10拆分自AMS)
├── ActivityManagerService       → 四大组件管理
├── PowerManagerService          → 电源管理
├── PackageManagerService        → 包管理(解析所有APK信息)
├── UserManagerService           → 多用户管理
└── DisplayManagerService        → 显示管理

核心服务(Core Services):
├── BatteryService               → 电池状态
├── UsageStatsService            → 使用统计
├── WebViewUpdateService         → WebView更新
└── BugreportManagerService      → Bug报告

其他服务(Other Services):
├── WindowManagerService         → 窗口管理
├── InputManagerService          → 输入事件
├── NetworkManagementService     → 网络管理
├── ConnectivityService          → 网络连接
├── AudioService                 → 音频管理
├── CameraService                → 相机管理
├── NotificationManagerService   → 通知管理
├── LocationManagerService       → 定位管理
└── ... 约100+个系统服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 7.4 服务启动的依赖关系

服务之间存在严格的启动顺序依赖:

AMS依赖 → PowerMS(需要电源管理能力)
PMS依赖 → Installer(需要安装能力)
WMS依赖 → AMS + InputMS(需要Activity管理和输入事件)
Launcher依赖 → AMS + PMS + WMS(需要所有核心服务就绪)

启动时序:
t=0s   ──── Installer, DeviceIdentifier
t=0.5s ──── AMS, PowerMS, LightsMS
t=1s   ──── PMS(扫描所有APK,耗时最长)
t=3s   ──── WMS, InputMS
t=4s   ──── NetworkMS, AudioMS, ...
t=5s   ──── 所有服务就绪 → 发送BOOT_COMPLETED广播
1
2
3
4
5
6
7
8
9
10
11
12

# 八、系统服务的注册与启动

# 8.1 ServiceManager的角色

ServiceManager是Binder机制中的"DNS服务器",管理所有系统服务的注册和查找:

ServiceManager工作原理:
┌──────────────────────────────────────────┐
│          ServiceManager (Context Manager) │
│  ┌────────────────────────────────────┐  │
│  │  服务注册表(HashMap)              │  │
│  │  "activity"    → AMS的Binder引用    │  │
│  │  "package"     → PMS的Binder引用    │  │
│  │  "window"      → WMS的Binder引用    │  │
│  │  "input"       → IMS的Binder引用    │  │
│  │  ...           → ...                │  │
│  └────────────────────────────────────┘  │
│                                          │
│  addService(name, binder)  ← 注册服务    │
│  getService(name)          ← 查找服务    │
└──────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 8.2 系统服务的注册过程

以AMS为例,展示服务注册的完整链路:

// SystemServer中启动AMS
private void startBootstrapServices() {
    // 1. 创建AMS实例
    ActivityTaskManagerService atm = mSystemServiceManager.startService(
            ActivityTaskManagerService.Lifecycle.class).getService();
    mActivityManagerService = ActivityManagerService.Lifecycle.startService(
            mSystemServiceManager, atm);
    
    // 2. 注册到ServiceManager
    mActivityManagerService.setSystemProcess();
    // 内部调用:
    // ServiceManager.addService("activity", this, /* allowIsolated= */ true);
}

// 应用层获取AMS
// Context.getSystemService(Context.ACTIVITY_SERVICE)
// 最终调用:ServiceManager.getService("activity")
// 返回AMS的Binder代理对象(BinderProxy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 8.3 SystemServiceManager的生命周期管理

// SystemServiceManager管理服务的生命周期
public void startBootPhase(int phase) {
    // 按阶段通知所有服务
    for (SystemService service : mServices) {
        service.onBootPhase(phase);
    }
}

// 启动阶段定义:
PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100    // 等待默认显示器
PHASE_LOCK_SETTINGS_READY = 480         // 锁屏设置就绪
PHASE_SYSTEM_SERVICES_READY = 500       // 系统服务就绪
PHASE_ACTIVITY_MANAGER_READY = 550      // AMS就绪
PHASE_THIRD_PARTY_APPS_CAN_START = 600  // 第三方应用可以启动
PHASE_BOOT_COMPLETED = 1000             // 启动完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 九、Launcher的启动与桌面显示

# 9.1 AMS启动Launcher的时机

当所有系统服务启动完成后,AMS会启动Home应用(Launcher):

// ActivityManagerService.java
public void systemReady(final Runnable goingCallback, ...) {
    // 1. 执行一系列准备工作
    // 2. 发送PHASE_ACTIVITY_MANAGER_READY
    // 3. 启动持久应用(persistent apps)
    
    // 4. 启动Home Activity(Launcher)
    mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
}

// ActivityTaskManagerService → RootWindowContainer
void startHomeOnDisplay(int userId, String reason, int displayId) {
    Intent homeIntent = getHomeIntent();  
    // 构造HOME类型的Intent
    // Action: Intent.ACTION_MAIN
    // Category: Intent.CATEGORY_HOME
    
    // 通过PMS查找匹配的Activity(即Launcher)
    ActivityInfo aInfo = resolveActivityInfo(homeIntent, ...);
    
    // 启动Launcher
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, ...);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 9.2 Launcher的角色与启动流程

Launcher启动流程:
AMS.systemReady()
    ↓
startHomeOnAllDisplays()
    ↓
解析HOME Intent → 找到Launcher应用
    ↓
startActivity() → 标准Activity启动流程
    ↓
Zygote fork新进程 → 创建Launcher进程
    ↓
Launcher.onCreate()
    ├── 加载桌面布局
    ├── 查询所有已安装应用(PackageManager.queryIntentActivities)
    ├── 创建应用图标网格
    └── 显示桌面
    ↓
用户看到桌面 → 系统启动完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 9.3 开机广播的发送

启动完成后的广播:
1. Intent.ACTION_LOCKED_BOOT_COMPLETED
   → 设备加密状态下发送(Direct Boot模式)
   → 只有声明了directBootAware的应用能收到

2. Intent.ACTION_BOOT_COMPLETED
   → 用户解锁后发送
   → 所有注册了该广播的应用都能收到
   → 很多应用利用这个广播实现"开机自启"
1
2
3
4
5
6
7
8
9

# 十、Application进程的创建过程

# 10.1 完整的应用启动链路

当用户点击Launcher中的应用图标时:

用户点击图标
    ↓
Launcher → startActivity(intent)
    ↓
Binder IPC → AMS.startActivity()
    ↓
AMS检查目标进程是否存在
    ├── 已存在 → 直接调度Activity
    └── 不存在 → 请求Zygote创建进程 ↓
    ↓
AMS → socket连接 → Zygote
    ↓
Zygote.fork() → 新进程
    ↓
新进程执行 ActivityThread.main()
    ↓
ActivityThread → 创建Application对象
    ↓
Application.onCreate()
    ↓
AMS调度 → 创建Activity → Activity.onCreate()
    ↓
View绘制 → 用户看到界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 10.2 AMS请求Zygote的通信过程

// AMS端:Process.java
public static ProcessStartResult start(String processClass, ...) {
    return ZYGOTE_PROCESS.start(processClass, ...);
}

// ZygoteProcess.java → 通过Socket发送请求
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args) {
    
    // 构造参数列表
    // 格式:每个参数一行,以换行符分隔
    // --runtime-args
    // --setuid=10086
    // --setgid=10086
    // --target-sdk-version=33
    // --nice-name=com.example.app
    // android.app.ActivityThread  ← 入口类
    
    DataOutputStream out = zygoteState.mZygoteOutputStream;
    out.writeInt(args.size());  // 参数数量
    for (String arg : args) {
        out.writeBytes(arg + "\n");
    }
    
    // 读取Zygote返回的PID
    DataInputStream in = zygoteState.mZygoteInputStream;
    int pid = in.readInt();
    return new ProcessStartResult(pid);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 10.3 ActivityThread.main():应用的真正入口

// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    // 1. 准备主线程的Looper
    Looper.prepareMainLooper();
    
    // 2. 创建ActivityThread实例
    ActivityThread thread = new ActivityThread();
    
    // 3. 关键步骤:attach到AMS
    thread.attach(false, startSeq);
    // 内部通过Binder调用AMS.attachApplication()
    // AMS收到后:
    //   - 记录进程信息
    //   - 回调bindApplication():创建Application对象
    //   - 调度待启动的Activity/Service/BroadcastReceiver
    
    // 4. 获取主线程Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    
    // 5. 进入消息循环(永不退出)
    Looper.loop();
    
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 十一、预加载机制与启动优化

# 11.1 Zygote预加载的内容

// ZygoteInit.java
static void preload() {
    // 1. 预加载Java类(约8000+个常用类)
    preloadClasses();
    // 读取 /system/etc/preloaded-classes 文件
    // 包括:android.app.Activity, android.widget.TextView,
    //       java.util.ArrayList, java.lang.String 等
    // 通过Class.forName()加载,触发类的<clinit>初始化
    
    // 2. 预加载资源
    preloadResources();
    // 加载framework-res.apk中的资源
    // 包括:系统主题、默认颜色、常用Drawable等
    
    // 3. 预加载共享库
    preloadSharedLibraries();
    // libandroid.so, libcompiler_rt.so, libjnigraphics.so, libmedia_jni.so等
    
    // 4. 预加载文字渲染资源
    preloadTextResources();
    // 字体文件、文字布局相关资源
    
    // 5. 预加载OpenGL驱动
    maybePreloadGraphicsDriver();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 11.2 预加载的内存效益分析

预加载的核心收益 — 内存共享:

假设系统运行了20个应用进程:

不预加载:
每个进程独立加载8000个类 → 每个进程约占用20MB → 总计400MB

预加载(通过Zygote + COW):
Zygote预加载20MB → fork后20个进程共享 → 总计仅20MB物理内存
只有修改过的内存页才会复制 → 每个进程额外仅约2MB → 总计60MB

节省:400MB - 60MB = 340MB(节省85%!)
1
2
3
4
5
6
7
8
9
10
11
12

# 11.3 预加载类的选择策略

preloaded-classes文件的生成策略:
1. Google通过采样统计确定需要预加载的类
2. 条件:在启动阶段被至少N个应用使用的类
3. 排除条件:
   - 只在少数应用中使用的特殊类
   - 过大的类(加载耗时太长)
   - 有副作用的静态初始化块

选择平衡点:
预加载太多 → Zygote启动变慢 + 浪费内存
预加载太少 → 应用启动变慢(需要额外加载)
1
2
3
4
5
6
7
8
9
10
11

# 11.4 启动速度优化策略

Android系统层面的启动优化:
├── Zygote预加载(减少进程创建时间)
├── USAP池(预先fork进程池)
├── PMS并行扫描(多线程扫描APK)
├── 延迟服务启动(非关键服务延后启动)
├── I/O预读(readahead系统调用)
└── 编译优化(AOT编译关键类)

应用层面的启动优化:
├── 减少Application.onCreate()耗时
│   ├── 延迟初始化非必要SDK
│   ├── 异步初始化(子线程)
│   └── 按需加载(用到时才初始化)
├── 减少主Activity布局复杂度
│   ├── 使用ViewStub延迟加载
│   └── 减少布局层级
├── 避免主线程I/O
│   ├── SharedPreferences异步写入
│   └── 数据库操作放子线程
└── 使用SplashScreen API(Android 12+)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 十二、Android启动中的关键设计思想

# 12.1 进程隔离与安全模型

Android的进程安全模型:
┌────────────────────────────────────┐
│  每个应用 = 独立的Linux进程          │
│  每个应用 = 独立的UID               │
│  每个应用 = 独立的文件系统沙箱        │
└────────────────────────────────────┘

进程创建时的安全设置:
fork() → setuid(appUid) → setgid(appGid)
      → setgroups(supplementaryGids)
      → SELinux域转换(u:r:untrusted_app:s0:...)
      → seccomp过滤(限制可用的系统调用)

结果:
应用A(UID=10001)无法访问应用B(UID=10002)的文件
应用无法直接访问系统关键目录
应用的系统调用受到限制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 12.2 分层启动的设计哲学

Android启动的分层设计:

Layer 0: 硬件/BootLoader    → 确保硬件可用
Layer 1: Linux Kernel       → 提供OS基础能力
Layer 2: Init进程           → 用户空间入口,启动守护进程
Layer 3: Zygote进程         → Java世界的入口,进程孵化器
Layer 4: SystemServer       → 系统服务中心
Layer 5: Launcher           → 用户交互入口

每一层只依赖下一层,不跨层依赖:
- Zygote不直接操作硬件
- SystemServer不直接fork进程(通过Zygote)
- 应用不直接访问内核(通过系统服务)
1
2
3
4
5
6
7
8
9
10
11
12
13

# 12.3 单一职责与服务化

设计原则:每个组件只做一件事

Init:          只负责启动其他进程 + 属性管理
Zygote:        只负责fork新进程
SystemServer:  只负责管理系统服务
ServiceManager: 只负责服务注册和查找
AMS:           只负责四大组件生命周期
PMS:           只负责包信息管理
WMS:           只负责窗口管理

好处:
- 某个服务崩溃不会影响整个系统
- 可以独立升级某个服务
- 权限边界清晰
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 12.4 预加载+COW的"空间换时间"哲学

这是Android系统中最巧妙的设计之一:

传统思路:按需加载(懒加载)
  优点:启动快,不浪费内存
  缺点:每个进程首次使用时都要加载,重复劳动

Android思路:Zygote预加载 + Fork COW
  1. Zygote启动时一次性加载所有常用资源(预加载阶段耗时较长)
  2. Fork子进程时通过COW共享物理内存(零拷贝)
  3. 子进程修改时才真正分配独立内存(按需分配)
  
结果:
  - 第一个进程(Zygote)启动较慢 → 可接受(只在开机时发生一次)
  - 后续所有应用进程启动很快 → 用户体验好
  - 物理内存只有一份 → 节省大量内存
  
这是典型的"一次投入,多次收益"的设计。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 十三、面试高频问题与深度分析

# 13.1 Zygote为什么用Socket而不用Binder通信?

原因分析:

1. 时序问题:
   Zygote启动时,ServiceManager还未启动
   → 无法注册Binder服务
   → 只能使用更底层的IPC(Socket)

2. Fork安全性:
   Binder是多线程模型(Binder线程池)
   fork()只复制调用线程,其他Binder线程不会被复制
   → 子进程的Binder线程池处于不一致状态 → 可能死锁
   
   Socket是单线程的select/poll模型
   → fork安全,不存在多线程问题

3. 使用场景简单:
   Zygote只需要接收"创建进程"请求
   → 不需要Binder的复杂双向通信能力
   → 简单的请求-响应模式,Socket足够
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 13.2 SystemServer为什么不直接启动,而要从Zygote fork?

原因:
SystemServer需要运行Java代码(AMS、PMS等都是Java写的)
→ 需要一个已经初始化好的Java虚拟机
→ Zygote已经创建了VM并预加载了类
→ fork Zygote = 免费获得一个初始化好的VM环境

如果SystemServer独立启动:
→ 需要自己创建VM → 慢
→ 需要自己加载系统类 → 慢
→ 预加载的资源无法与应用进程共享 → 浪费内存
1
2
3
4
5
6
7
8
9
10

# 13.3 Android为什么有两个Zygote(32位和64位)?

现代Android设备同时支持32位和64位应用:

zygote64  → fork 64位应用进程
zygote32  → fork 32位应用进程

原因:
- ABI兼容性:32位应用无法在64位进程中运行
- 不同的共享库路径:/system/lib vs /system/lib64
- 不同的linker:/system/bin/linker vs /system/bin/linker64

PMS在安装APK时会检测其ABI,标记为32位或64位
AMS在启动应用时,根据标记选择对应的Zygote来fork
1
2
3
4
5
6
7
8
9
10
11
12

# 13.4 如何观察系统启动过程?

# 1. 查看启动日志
adb logcat -b events | grep boot

# 2. 查看系统启动时间
adb shell cat /proc/bootprof         # MTK平台
adb shell dumpsys bootinfo           # 通用

# 3. 使用bootchart分析
adb shell 'touch /data/bootchart/enabled'
# 重启后导出数据
adb pull /data/bootchart/
# 使用bootchart工具生成可视化报告

# 4. 查看Zygote预加载耗时
adb logcat | grep "Preloading"
# 典型输出:
# Preloading classes... (took 1234ms)
# Preloading resources... (took 567ms)
# Preloading shared libraries... (took 89ms)

# 5. 使用systrace/perfetto分析启动
adb shell perfetto --config :boot --txt -o /data/misc/perfetto-traces/boot.perfetto-trace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 十四、ActivityThread深入分析

ActivityThread是Android应用进程的核心类,它的main方法是整个应用进程的入口。为什么我们平时将ActivityThread称之为UI线程或者主线程?因为应用进程被创建之后首先执行的就是ActivityThread的main方法。

# 14.1 ActivityThread核心流程

ActivityThread的main方法主要执行了以下操作:

ActivityThread核心流程:

ActivityThread#main()
├── Looper.prepareMainLooper()  → 初始化主线程Looper
├── new ActivityThread()        → 创建ActivityThread实例
├── thread.attach()             → 与AMS建立通信,创建Application
│   ├── AMS.attachApplication()  → 通过Binder调用AMS
│   ├── bindApplication()        → 设置进程信息
│   ├── makeApplication()        → 反射创建Application对象
│   └── callApplicationOnCreate() → 执行Application.onCreate()
└── Looper.loop()               → 开启消息循环(永不退出)
1
2
3
4
5
6
7
8
9
10
11

ActivityThread是应用程序与系统之间的桥梁,主要功能包括:

  1. 应用程序生命周期管理:负责管理应用程序的启动、暂停、恢复、停止和销毁等阶段,通过与AMS进行通信,接收生命周期回调。
  2. Activity管理和调度:负责创建、启动、暂停、恢复、停止和销毁Activity,并处理Activity之间的切换和交互。
  3. 消息处理和线程调度:使用Handler和Looper机制处理来自系统和应用程序的消息,并将其分发给相应的处理器。
  4. 应用程序上下文管理:负责管理应用程序的上下文,包括全局的Context对象和资源访问。

# 14.2 Application启动流程

App点击桌面图标启动Application的完整流程:

Application启动核心路径:

ActivityManagerService#startProcessLocked()
→ Process#start()
→ ActivityThread#main()               // 入口
→ ActivityThread#attach()             // 与AMS建立连接
→ AMS#attachApplication()            // Binder调用
→ AMS#attachApplicationLocked()      // 进程启动完成
→ thread.bindApplication()           // 回到ActivityThread
→ ActivityThread.ApplicationThread#bindApplication()
→ ActivityThread#handleBindApplication()  // 处理bind逻辑
    ├── 设置进程pid,初始化进程信息
    ├── LockedApk.makeApplication()   // 反射创建Application
    │   └── 同时创建ContextImpl并关联
    └── mInstrumentation.callApplicationOnCreate()
        └── Application.onCreate()    // 开发者入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

核心要点总结:

  • 应用进程启动 → 创建Instrumentation → 创建Application对象 → 创建Application相关的ContextImpl对象
  • 每个应用进程对应一个Instrumentation,对应一个Application
  • Instrumentation与Application都是通过Java反射机制创建
  • Application创建过程中会同时创建一个ContextImpl对象,并建立关联

# 14.3 Activity启动入口

ActivityThread中启动Activity的核心流程:

Activity创建核心路径:

ActivityThread.handleLaunchActivity()
→ ActivityThread.performLaunchActivity()
    ├── mInstrumentation.newActivity()  // 反射创建Activity
    ├── createBaseContextForActivity()  // 创建ContextImpl
    ├── activity.attach()               // 初始化Activity
    │   ├── attachBaseContext()         // 设置基础上下文
    │   └── new PhoneWindow()          // 创建窗口对象
    └── mInstrumentation.callActivityOnCreate()
        └── Activity.onCreate()        // 开发者入口
1
2
3
4
5
6
7
8
9
10
11

# 十五、Context上下文设计

# 15.1 Context设计目的

Android设计Context上下文的概念,是为了提供应用程序访问系统资源和执行特定操作的接口。Context在Android开发中扮演着重要的角色:

  1. 访问系统资源:允许应用程序访问包名、资源文件、数据库、SharedPreferences、系统服务等
  2. 启动组件:提供启动Activity、Service、BroadcastReceiver等组件的能力
  3. 获取应用程序级别信息:如包名、资源、文件目录等
  4. 访问系统服务:网络服务、传感器服务、位置服务等
  5. 安全性和权限管理:获取权限信息、检查和请求权限

# 15.2 Context类的设计

Context类继承关系:

Context (抽象类)
├── ContextImpl (真正的实现类)
└── ContextWrapper (代理/包装类)
    ├── Application
    ├── Service
    └── ContextThemeWrapper
        └── Activity
1
2
3
4
5
6
7
8
9
  • ContextWrapper:只是一个包装类,构造函数中必须包含一个真正的Context引用,调用ContextWrapper的方法都会被转向其所包含的真正Context对象
  • ContextImpl:真正实现了Context中的所有函数,应用程序中所调用的各种Context类的方法,其实现均来自于该类
  • Activity继承自ContextThemeWrapper(包含主题相关接口),Service和Application直接继承ContextWrapper(不需要主题)

# 15.3 Context作用域

不同类型的Context使用能力不同:

功能 Activity Application Service
启动Activity ✓ △(需FLAG_ACTIVITY_NEW_TASK) △
弹出Dialog ✓ ✗ ✗
启动Service ✓ ✓ ✓
发送Broadcast ✓ ✓ ✓
Layout Inflate ✓ △(使用系统默认主题) △

一个App中Context的数量 = Application(1) + N个Activity + N个Service

# 十六、组件通信Intent设计

# 16.1 Intent设计思想

Intent(意图)用于在不同组件之间传递消息和执行操作,设计思想是实现组件之间的松耦合通信和交互。Intent提供了一种统一的机制,使得Android应用程序中的各个组件可以相互协作,共享功能和数据。

Intent的核心设计模式:

1. 命令模式(Command Pattern)
   Intent封装了"动作+数据"的组合,调用方不需要知道具体的接收方
   → startActivity(new Intent(ACTION_VIEW, uri))
   → 系统通过PMS匹配最合适的组件来处理

2. 显式Intent vs 隐式Intent
   显式:明确指定目标组件
   → new Intent(this, TargetActivity.class)
   → 直接通过ComponentName定位
   
   隐式:通过Action/Category/Data描述意图
   → new Intent(Intent.ACTION_SEND)
   → PMS通过IntentFilter匹配合适的组件
   → 可能弹出选择器让用户选择

3. Intent的解析过程(PMS内部)
   IntentResolver.queryIntent()
   → 遍历所有已注册的IntentFilter
   → 按Action → Category → Data三级匹配
   → 返回匹配结果列表(ResolveInfo)

4. Intent的数据传输机制
   Intent → Parcel序列化 → Binder传输 → Parcel反序列化 → Intent
   → 整个过程是深拷贝,发送方和接收方持有的是不同对象
   → Binder缓冲区限制1MB,大数据不适合通过Intent传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 16.2 Bundle与数据传递

Intent传递数据和Bundle传递数据本质是一回事,Intent传递时内部调用了Bundle。Bundle只是一个信息的载体,内部其实就是维护了一个Map<String,Object>。

需要注意的是:

  • Intent传递数据的限制:Intent中的数据通过Binder机制传输,Binder事务缓冲区大小限定在1MB,且这个空间是进程共享的
  • 序列化问题:跨进程传递数据需要序列化(Serializable或Parcelable),这是值传递(深拷贝)
  • Fragment间传递:Fragment.setArguments(Bundle)不涉及跨进程,传递的是对象引用,不存在序列化开销
  • 大数据传递方案:对于Bitmap等大数据,应传递drawable_id、路径或URL,从数据源还原数据

# 16.3 PendingIntent设计

PendingIntent是一种特殊的Intent,用于在某个事件结束后执行特定的Action。即便创建该PendingIntent对象的进程被杀死了,这个PendingIntent对象在其他进程中还是可用的。常见应用场景包括短信、闹钟、通知栏点击等。

PendingIntent的底层原理:

1. 创建过程
   PendingIntent.getActivity(context, requestCode, intent, flags)
   → 通过AMS.getIntentSender()在系统进程中注册
   → AMS创建PendingIntentRecord保存在内存中
   → 返回一个IIntentSender的Binder代理给调用方

2. 执行过程
   通知栏点击 → NotificationManager通过PendingIntent.send()
   → AMS.sendIntentSender()
   → 从PendingIntentRecord中取出保存的Intent
   → 以原始调用方的身份和权限执行Intent
   
3. 安全设计
   PendingIntent携带了创建者的UID/PID
   → 执行时使用创建者的身份,而非触发者的身份
   → 这就是为什么Notification能跨进程启动创建者的Activity

4. flags含义
   FLAG_ONE_SHOT     → 只能使用一次
   FLAG_NO_CREATE    → 如果不存在则返回null
   FLAG_CANCEL_CURRENT → 取消旧的,创建新的
   FLAG_UPDATE_CURRENT → 更新旧的extras数据
   FLAG_IMMUTABLE    → PendingIntent不可修改(Android 12+推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 十七、Android硬件抽象层

# 17.1 HAL层介绍

Android硬件抽象层(Hardware Abstraction Layer,HAL)是Android系统架构中的重要组成部分,提供了一个标准化的接口,用于在操作系统和底层硬件之间进行通信和交互。

HAL的设计旨在实现硬件的抽象和解耦,使得Android系统可以在不同的硬件平台上运行,而无需对上层应用程序进行修改。

HAL层在系统中的位置与作用:

Framework层 (Java)
    ↓ JNI调用
Native服务层 (C++)
    ↓ dlopen加载HAL模块
HAL层 (.so动态库)
    ↓ 系统调用
Linux内核驱动

HAL的核心价值:
1. 保护厂商知识产权
   → Linux内核使用GPL协议,驱动代码必须开源
   → HAL运行在用户空间,使用Apache协议,厂商可以闭源
   → 厂商将核心算法放在HAL层,只在内核实现基本IO

2. 提供统一接口
   → 不同厂商的Camera硬件各不相同
   → 但CameraHAL接口定义是统一的
   → Framework层调用HAL接口时不需要关心具体硬件
   
3. HAL的演进
   Legacy HAL (Android 7.0-):.so直接加载到Framework进程
   HIDL HAL (Android 8.0+):HAL运行在独立进程,通过HIDL接口通信
   AIDL HAL (Android 11+):使用稳定版AIDL代替HIDL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 17.2 HAL层设计

HAL层的关键设计包括:

  1. 接口定义:定义了一组标准化的接口,描述摄像头、传感器、音频、蓝牙、Wi-Fi等硬件功能和操作
  2. HAL实现:每个硬件厂商根据接口定义实现相应的HAL库(.so文件),负责与底层硬件通信
  3. 设备树:描述硬件配置和功能的数据结构,使HAL能够动态识别和加载适当的硬件驱动
  4. 与上层框架的交互:通过标准化接口,使上层应用框架可以与硬件交互,而无需关心具体硬件实现

# 17.3 系统架构分层

Android系统架构:

应用层
├── 四大组件 (Activity, Service, BroadcastReceiver, ContentProvider)
└── 第三方应用

应用框架层 (Java)
├── AMS → 管理组件生命周期
├── PMS → 管理应用安装
├── WMS → 管理窗口
└── 其他系统服务

C/C++库 + Android运行时
├── 核心库 (Java/C/C++/媒体库)
├── ART虚拟机 (Dex → 本地机器码)
└── JNI桥接

HAL层
└── 标准化硬件接口

Linux内核层
├── 硬件驱动
├── 进程/内存管理
├── Binder驱动
└── 网络协议栈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
上次更新: 2026/06/10, 11:13:41
ARouter路由实践设计
Binder通信原理

← ARouter路由实践设计 Binder通信原理→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式