Android 操作系统并不是从零开始构建的,而是建立在 Linux 内核之上的一个高度定制的软件栈。理解 Android 操作系统的整体架构,是深入理解任何一个子系统(Binder、SurfaceFlinger、AMS、Zygote 等)的前提。本文将系统性地介绍 Android 操作系统的四层架构、Linux 内核为 Android 所做的定制修改,以及 Android 选择 Linux + Binder IPC 架构的深层原因。
一、Android 操作系统的四层架构
1.1 经典分层模型
┌──────────────────────────────────────────────────────┐ |
1.2 各层职责详解
第一层:Linux Kernel(Linux 内核)
Linux 内核是 Android 平台的基石,负责:
- 进程管理:创建、调度、终止进程和线程(CFS 调度器)
- 内存管理:虚拟内存、物理页面分配(buddy system)、进程间内存隔离(页表)、内存回收(kswapd)
- 设备驱动:硬件设备的抽象和访问控制
- 文件系统:ext4 / erofs / f2fs / tmpfs 等文件系统支持
- 网络协议栈:TCP/IP、WiFi、蓝牙、NFC
- 安全模型:基于 UID/GID 的进程隔离、SELinux、Capabilities、seccomp
**CFS (Completely Fair Scheduler)**:Linux 内核的默认调度器,基于红黑树维护所有可运行任务,按虚拟运行时间(vruntime)排序。调度器总是选择 vruntime 最小的任务执行——即”获得 CPU 时间最少的任务优先”。
内存管理核心机制:
- VMA(Virtual Memory Area):每个进程的地址空间被划分为多个 VMA,描述连续虚拟地址区域的属性(代码段、堆、栈、mmap 区域等)
- Page Fault:当进程访问尚未映射的虚拟地址时,触发缺页异常。内核的 page fault handler 根据 VMA 的属性分配物理页面或从磁盘加载数据
- Buddy System:物理页面分配器,以 2 的幂次大小为分配单位,通过伙伴合并机制减少内存碎片
第二层:HAL(硬件抽象层)
HAL 是 Android 架构中最重要的抽象之一。每个硬件组件都有一个 HAL 模块(通常以 .so 文件形式存在),框架层通过 HAL 接口调用硬件,而不直接与内核驱动交互。
App → Android Framework → HAL Interface → HAL Implementation → Kernel Driver → Hardware |
Android 8+ 引入了 HIDL(HAL Interface Definition Language)将 HAL 服务运行在独立进程中,进一步隔离了框架层和硬件实现层,这是 Treble 架构的核心。
Binderized HAL vs Passthrough HAL:
- Binderized HAL:HAL 实现在独立进程中,通过 Binder IPC 通信。接口用 HIDL 或 AIDL 定义。Android 8+ 推荐
- Passthrough HAL:HAL 实现以 .so 形式加载到框架进程(如 mediaserver)的地址空间中。Android 7 及之前的模式
第三层:Native Libraries + Android Runtime
Native C/C++ Libraries(原生库):
- Bionic:Android 定制的 C 标准库,替代 glibc。设计目标:更小、更快、BSD 许可
- SurfaceFlinger:显示合成引擎,将所有可见窗口的 buffer 合成为最终显示帧
- Media Framework:音视频编解码框架(Stagefright)
- SQLite:嵌入式关系型数据库
- OpenGL ES / Vulkan:3D 图形渲染 API
- Skia:2D 图形渲染引擎(同时也是 Flutter 的渲染引擎)
**Android Runtime (ART)**:
- AOT (Ahead-Of-Time) 编译:安装时把 DEX 字节码编译为 native 指令
- JIT (Just-In-Time) 编译:运行时对热点代码进行即时编译
- GC(垃圾回收):并发压缩回收、分代回收(Android 10+)
- Profile-guided 优化:基于应用使用模式优化编译
第四层:Java API Framework(Java 框架层)
这是 Android 应用开发的核心 API:
- ActivityManagerService — 四大组件管理
- WindowManagerService — 窗口管理
- PackageManagerService — 包管理
- ContentProvider — 数据共享
- View System — UI 组件体系
第五层:System Apps(系统应用层)
预装的系统级应用,与第三方应用共享同一运行时。
二、Linux 内核为 Android 所做的关键修改
Android 并不是简单地拿一个标准 Linux 内核来用。Google 对 Linux 内核做了大量的定制修改,这些修改通过 Android Mainline Project 逐步合入 Linux 主线。
2.1 Binder IPC 驱动程序
Binder 是 Android 最核心的 IPC(进程间通信)机制,作为内核驱动实现:
// drivers/android/binder.c (Android 内核中的 Binder 驱动) |
Binder 驱动在 /dev/binder 上为用户空间提供接口。Android 10+ 引入了多 Binder 域:
/dev/binder— 系统服务通信(framework 和 app 之间)/dev/hwbinder— HIDL HAL 服务通信/dev/vndbinder— Vendor 域 HAL 服务通信
每个 Binder 域有独立的 context manager,实现了不同安全等级的 IPC 隔离。
2.2 ashmem(Android Shared Memory)
ashmem 是 Android 特有的共享内存机制,支持通过名称引用和引用计数自动回收:
// drivers/staging/android/ashmem.c |
在 Android 10+ 中,ashmem 正逐步被 Linux 标准的 memfd_create() 替代。memfd 提供了类似的功能(基于 fd 的匿名内存),而且支持 sealing(防止共享者修改内容)。
2.3 Low Memory Killer (LMK) → lmkd
Android 最初在内核中实现了低内存杀手(LMK)驱动,在内存不足时选择性杀死进程。从 Android 9 开始,这个功能被迁移到用户空间的 lmkd 守护进程:
// system/memory/lmkd/lmkd.cpp |
2.4 Wakelocks 和电源管理
Android 的电源管理非常激进——设备默认进入 suspend 状态,由 wakelock 机制决定何时保持唤醒:
// drivers/power/wakelock.c (Android 内核修改) |
Android 新的电源管理通过 PowerManagerService 和 WakeLock 类实现,底层驱动接口逐步向 Linux 主线的 autosleep 机制靠拢。
2.5 Android 内核与 Linux 主线的合入
从 Android 11 开始,Google 通过 Android Generic Kernel Image (GKI) 项目将 Android 内核修改逐步合入 Linux 主线或封装为独立模块。目标是:
- GKI 1.0 (Android 11):内核版本 5.4,厂商模块与内核解耦
- GKI 2.0 (Android 12+):内核版本 5.10+,更大的主线上游覆盖率
三、Android 的 Init 系统 vs 传统 Linux Init
3.1 Android init 与 systemd / sysvinit 的对比
| 特性 | Android init | systemd | sysvinit |
|---|---|---|---|
| 配置语言 | init.rc(自定义语言) | unit 文件 (.service, .target 等) | shell 脚本 |
| 依赖管理 | 触发器机制 (on property:) | 显式依赖 (Requires=, Wants=) | 脚本顺序(无依赖) |
| 服务监控 | 内置(SIGCHLD + epoll) | 内置(cgroups 监控) | 需要额外守护进程 |
| 并行启动 | 事件驱动并行 | Socket-based 并行 | 串行 |
| 属性存储 | 内置 Property Service | systemd 不支持 | N/A |
| 设备节点管理 | 内置 ueventd | udevd (systemd-udevd) | udev / mdev |
3.2 为什么 Android 不直接使用 systemd
- 资源开销:systemd 设计为功能完备的 init 系统,包含 journald、logind、networkd 等大量组件,这些对嵌入式移动设备是过度设计
- 启动性能:Android 的设备节点管理和服务启动优化极度精简,专注于亚秒级启动
- Android 特化需求:android init 深度集成了 property service、SELinux 上下文管理、USB gadget 配置等 Android 特有的功能
四、为什么 Android 选择 Linux 内核 + Binder IPC?
4.1 选择 Linux 的原因
- 成熟的驱动生态:Linux 已有大量 ARM 处理器和外设的优质驱动
- 活跃的开发社区:持续的 bug 修复、安全补丁、新硬件支持
- 经过验证的安全模型:UID/GID 隔离、SELinux、Capabilities
- 开源许可兼容:GPL v2 内核与 Apache 2.0 用户空间的组合在商业和法律上可行
4.2 选择 Binder 代替 D-Bus / Unix Socket 的原因
Binder 的设计由前 BeOS 工程师 Dianne Hackborn 主导,针对移动设备进行了深入优化:
Binder 相比 D-Bus 的优势:
- 零拷贝传输:通过 mmap 在内核空间映射接收缓冲区(1MB - 8MB),传输大块数据时避免用户空间复制
- 调用者身份保证:内核驱动保证
sender_euid/sender_pid不被伪造 - 引用计数和死亡通知:自动管理跨进程对象引用
- 线程池管理:Binder 驱动内建线程池,Binder 调用在服务端自动分配线程
五、Fuchsia:Android 的长期替代方案
5.1 Zircon 与 Linux 的关键差异
| 特性 | Linux(Android 使用) | Zircon(Fuchsia 使用) |
|---|---|---|
| 内核架构 | 宏内核(Monolithic) | 微内核(Microkernel) |
| 驱动模型 | 内核空间驱动 | 用户空间驱动(部分) |
| IPC 机制 | Binder(内核模块) | Channel(原生内核对象) |
| 调度模型 | CFS | 基于 deadline 的调度器 |
| 能力模型 | UID/GID + SELinux | 基于 capability 的对象句柄 |
5.2 为什么 Android 短期内不会迁移到 Fuchsia
- 生态惯性:数十亿设备和数以百万计的 App 依赖 Linux 内核
- 硬件驱动:Linux 的驱动覆盖范围远超 Zircon
- 工程成本:迁移整个运行时时到新内核 API 是天文数字的工程
六、核心面试题
Q1:Android 为什么使用 Linux 内核而不是其他内核(如 BSD、L4)?
答:(1) Linux 在 ARM 平台上有最成熟的硬件驱动生态,而移动设备 SoC 种类繁多;(2) Linux 社区活跃,持续获得安全补丁和性能优化;(3) Linux 的 GPL v2 许可与 Android 用户空间的 Apache 2.0 许可兼容;(4) Linux 的 UID/GID 隔离模型天然适合 Android 的每个 App 一个 UID 的设计。
Q2:Binder 在 Android 中为什么比传统的 Unix Domain Socket 更适合做 IPC?
答:(1) 零拷贝:Binder 通过 mmap 在内核空间预分配接收缓冲区,避免了一次用户空间拷贝。(2) 身份认证:Binder 驱动在每次事务中携带 sender_euid 和 sender_pid,服务端可以信任这些信息。(3) 死亡通知:Binder 通过 linkToDeath 自动通知服务端客户端进程的退出。(4) 对象引用计数:Binder 驱动自动管理跨进程对象引用。
Q3:Android 的 HAL 层与标准 Linux 的驱动模型有什么不同?
答:标准 Linux 驱动模型是:用户空间 → 系统调用 → 内核驱动 → 硬件。Android HAL 在驱动之上增加了一层抽象:用户空间 → HAL 接口 → HAL 实现 → 内核驱动 → 硬件。上层框架使用统一的 HAL 接口,厂商只需实现 HAL 接口而不需要修改框架代码。HIDL(Android 8+)进一步将 HAL 实现放入独立进程。
Q4:lmkd(用户空间 LMK)和内核 LMK 相比有什么优势?
答:(1) 策略硬编码在内核中 → 策略在用户空间,更新无需改内核;(2) 内核无法读取进程的 importance 等 framework 层信息 → lmkd 可通过 AMS 获取 OOM ADJ;(3) 内核基于简单内存阈值触发 → lmkd 可通过 /proc/pressure/memory 获取内存压力事件、通过 cgroup 进行精细控制。
Q5:Fuchsia 的 Zircon 微内核架构相比 Linux 宏内核有什么优势?为什么 Google 在 Android 之外又开发 Fuchsia?
答:微内核架构优势:(1) 故障隔离——驱动 crash 不会导致整个系统崩溃,内核可重启驱动进程;(2) 更小的 TCB(Trusted Computing Base);(3) 可更新性——无需重启系统即可更新驱动。Google 开发 Fuchsia 的动机包括:Linux 开发流程和许可证不完全符合 Google 利益、GKI 无法从根本上解决版本碎片化、Google 希望在新一代 OS 的 IPC、调度器、安全架构方面有完整控制权。
六、Linux 内核关键子系统在 Android 中的应用
6.1 CFS 调度器与 Android 的任务管理
CFS(Completely Fair Scheduler)是 Linux 内核的默认调度器,从 Linux 2.6.23 开始使用。Android 进程的调度完全依赖 CFS。
CFS 的核心数据结构是红黑树,按虚拟运行时间(vruntime)组织所有可运行任务。vruntime 的计算公式:
vruntime += (actual_runtime) * (NICE_0_LOAD / task_weight)
其中 task_weight 由 nice 值决定——nice 值越低(优先级越高),weight 越大,vruntime 增长越慢,因此获得更多 CPU 时间。
Android 依赖 Linux 的 cgroup(Control Groups)来对任务进行分组管理和资源限制:
// Android 使用 cgroup 隔离不同优先级的任务 |
Android 8+ 引入了 cpuset cgroup,将前台应用绑定到”大核”(big cores),后台任务绑定到”小核”(little cores),实现 energy-aware scheduling(EAS)——在性能和功耗间找到平衡点。
6.2 VFS(Virtual File System)与 Android 文件系统
Linux 的 VFS 层为 Android 提供了统一的文件系统接口,使得不同文件系统(ext4、f2fs、erofs、sdcardfs)可以无缝共存:
用户空间 open/read/write/close |
f2fs(Flash Friendly File System):三星为 NAND flash 设备优化的文件系统。Android 在 Pixel 设备上默认使用 f2fs 作为 data 分区文件系统。相比 ext4,f2fs 在随机写入和小文件操作上有显著性能提升。
erofs(Enhanced Read-Only File System):华为贡献的只读文件系统,Android 10+ 用于 system 分区。相比 ext4,erofs 支持透明压缩并减少了读放大。
6.3 Linux 网络协议栈与 Android 的网络限制
Android 对网络栈的定制主要集中在安全控制:
// net/ipv4/af_inet.c — Android 的网络创建限制 |
Android 还通过 iptables/netfilter 实现:
- 应用级防火墙:限制后台应用的网络访问(Android 7+)
- Data Saver:白名单机制,仅允许前台应用或用户授权的应用使用数据
- 私有 DNS:基于 DNS-over-TLS 的系统级加密 DNS(Android 9+)
6.4 Android 的 seccomp-bpf 严格化
Android 8.0 开始对所有应用进程启用 seccomp-bpf:
// bionic/libc/seccomp/seccomp_policy.cpp |
seccomp-bpf 过滤在 bionic libc 初始化阶段安装。整个过程是不可逆的——一旦安装,进程就不能再增加系统调用的权限。
七、Android 系统启动流程
7.1 Boot ROM → Kernel → Init 的启动链
Boot ROM (出厂固化) |
7.2 Zygote 的进程预加载机制
Zygote 是 Android 特有的进程孵化器。它在启动时预加载所有应用的公共类和资源:
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java |
预加载后,Zygote 的内存页大部分是共享的——所有从 Zygote fork 的应用进程共享这些页的物理内存(COW——Copy On Write)。这大幅减少了每个应用进程的启动时间和内存占用。
八、Android 安全架构概览
8.1 纵深防御模型
Android 的安全架构采用多层纵深防御策略:
- 应用层沙箱:每个 App 在自己的 UID 下运行
- 权限系统:运行时权限 + 安装时权限
- SELinux:强制访问控制
- seccomp:系统调用过滤
- 应用签名:签名一致的 App 可共享 UID
- Verified Boot:从硬件根信任的完整验证链
8.2 SELinux 在 Android 中的应用
Android 从 4.3 引入 SELinux,4.4 起强制开启 Enforcing 模式。SELinux 的核心概念:
进程 (domain) → 操作 (class:permission) → 资源 (type) |
关键 domain 定义:
untrusted_app:第三方应用system_app:系统签名应用priv_app:特权应用(比 system_app 有更多权限)isolated_app:隔离进程(如 WebView renderer)
Android 8+ 的 Treble 架构要求 system 和 vendor 的 sepolicy 分离。厂商只能修改 vendor/ 下的 sepolicy,不能修改 system/ 下的平台 sepolicy。这保证了系统升级不破坏厂商的安全策略,反之亦然。
AOSP 核心路径参考:
drivers/android/binder.c— Binder 驱动drivers/staging/android/ashmem.c— 匿名共享内存drivers/power/wakelock.c— 电源管理system/core/init/— Android init 进程system/memory/lmkd/— 用户空间低内存杀手system/sepolicy/— SELinux 策略hardware/interfaces/— HIDL HAL 接口定义frameworks/native/cmds/servicemanager/— Binder 服务管理器frameworks/native/services/surfaceflinger/— 显示合成引擎frameworks/base/core/java/com/android/internal/os/ZygoteInit.java— Zygote 初始化bionic/libc/seccomp/seccomp_policy.cpp— seccomp 策略
九、Android 与嵌入式 Linux 的对比
许多开发者误以为 Android 就是 “Linux + Java”。实际上 Android 在很多方面与传统 Linux 发行版有根本差异:
9.1 Bionic vs glibc
Bionic 是 Android 自行开发的 C 标准库,替代 Linux 标准的 glibc。关键差异:
| 特性 | glibc | Bionic |
|---|---|---|
| 代码大小 | ~2.5MB | ~400KB |
| 许可证 | LGPL | BSD |
| 线程实现 | NPTL | 基于 futex 的简化实现 |
| POSIX 兼容 | 几乎完整 | 子集(裁剪了不适用于移动设备的 API) |
| 内存分配 | ptmalloc3 | jemalloc(Android 10+) / dlmalloc(旧版) |
| 编译优化 | 通用 | 为 ARM/i386 优化 |
| C++ 异常 | 完整支持 | 支持但不完整(某些 corner case 可能不同) |
Bionic 的设计哲学:更小、更快、BSD 许可。它的 printf 实现比 glibc 快约 30%,因为它省略了 POSIX locale 和复杂的 internationalization 支持。
9.2 Android 的文件系统布局
Android 不使用传统的 FHS(Filesystem Hierarchy Standard):
| 目录 | Android | 传统 Linux (FHS) |
|---|---|---|
| 系统二进制 | /system/bin | /usr/bin, /bin |
| 系统库 | /system/lib64 | /usr/lib64, /lib64 |
| 配置文件 | /system/etc | /etc |
| 应用数据 | /data/data/ |
/home/ |
| 临时文件 | /data/local/tmp | /tmp |
| 设备文件 | /dev | /dev |
| 厂商分区 | /vendor | N/A(无对应) |
| 产品分区 | /product | N/A |
这种布局的设计考量:
- 区分只读分区(/system)和读写分区(/data),便于系统升级(OTA)
- /vendor 独立于 /system,实现 Treble 架构的厂商-平台分离
- /product 用于 OEM 定制,进一步分离运营商/OEM 的修改
9.3 Android 的启动与 A/B OTA
Android 支持 A/B 分区无缝更新(Seamless Updates):
正常启动: |
9.4 Android 不是传统 Linux 发行版
总结差异:
| 方面 | 传统 Linux (Debian/Ubuntu) | Android |
|---|---|---|
| C 库 | glibc | Bionic |
| init 系统 | systemd / sysvinit | 自定义 init(init.rc) |
| IPC | D-Bus / Unix Socket | Binder |
| 显示服务器 | X11 / Wayland | SurfaceFlinger |
| 包管理 | apt / dpkg / rpm | APK / PackageManager |
| 进程模型 | fork/exec | Zygote 预加载 + fork |
| 电源管理 | ACPI / systemd-logind | Wakelock / PowerManager |
| 系统升级 | apt upgrade | A/B OTA |
这些差异反映了 Android 团队的刻意设计选择——专为移动设备裁剪和优化。Android 并非”在 Linux 上跑 Java”,而是一个深度修改的操作系统,其基础是 Linux 内核,但用户空间几乎完全是自建的。



