Android内核驱动Linux设备驱动工程 - 第1节
1. Linux内核与Android系统概述
Linux内核是一个宏内核(Monolithic Kernel),但吸收了微内核的设计思想,通过模块机制实现动态扩展。其核心架构分为以下几个层次:
关键认知: Linux内核并非纯粹的宏内核,而是“宏内核 + 模块化”的混合体。驱动开发者主要工作在内核空间,与硬件直接交互。
1.1.1 内核空间与用户空间
Linux 通过 CPU 特权级(x86 的 Ring 0 ~ Ring 3,ARM 的 EL0 ~ EL3)隔离内核与用户程序:
- 内核空间:运行在最高特权级,可访问所有硬件资源。驱动、调度、内存管理均在此运行。
- 用户空间:运行在最低特权级,通过系统调用陷入内核。应用程序、C库、守护进程在此运行。
驱动开发者视角: 设备驱动运行在内核空间,一个指针错误就可能导致系统崩溃(Oops)。调试手段主要是
printk、ftrace、kgdb。
1.1.2 内核子系统概览
| 子系统 | 核心职责 | 驱动开发者关注点 |
|---|---|---|
| 进程管理 | 创建/调度/销毁进程,管理CPU时间片 | 驱动中的并发控制(spinlock/mutex) |
| 内存管理 | 虚拟地址映射、页分配、slab缓存 | DMA缓冲区分配、kmalloc/vmalloc选择 |
| 文件系统 | VFS抽象层,支持ext4/btrfs等 | 驱动通过file_operations暴露设备节点 |
| 网络协议栈 | TCP/UDP/IP协议实现,Socket接口 | 网络设备驱动(NAPI、sk_buff) |
| 设备驱动 | 字符/块/网络设备框架,中断处理 | 核心工作区:probe、open、ioctl、中断 |
| 安全模块 | SELinux、Capabilities、密钥管理 | 驱动需考虑权限检查(capable()) |
1.2 Android系统层次结构
Android 基于 Linux 内核,但在其之上构建了完整的应用框架层和运行时环境。整体层次从下到上分为:
1.2.1 各层职责详解
- 应用层:用户直接交互的界面,使用 Java/Kotlin 开发,运行在 ART 之上。
- 应用框架层:提供四大组件(Activity、Service、ContentProvider、BroadcastReceiver)和系统服务(WindowManager、PackageManager 等)。
- 系统运行时层:ART 负责执行 Dex 字节码;Native 库提供底层能力(Binder IPC、SurfaceFlinger、Media 编解码)。
- 硬件抽象层 (HAL):驱动开发者最常接触的接口层。HAL 封装内核驱动,向上提供稳定 API,使框架层不依赖具体内核实现。
- Linux 内核层:标准 Linux 内核 + Android 特有增强(wakelock、ashmem、binder 驱动等)。
重要区别: 标准 Linux 的驱动直接暴露
/dev 节点给用户空间;Android 则强制通过 HAL 封装,框架层不直接访问内核节点。这意味着 Android 驱动开发者既要写内核驱动,也要写对应的 HAL 模块。
1.3 Android与标准Linux的区别
Android 虽然使用 Linux 内核,但在用户空间架构、驱动模型、电源管理、IPC 机制等方面与标准 Linux 发行版有显著差异。下表总结了核心区别:
| 对比维度 | 标准 Linux | Android |
|---|---|---|
| 用户空间 | GNU C库 + X11/Wayland + 桌面环境 | Bionic libc + SurfaceFlinger + ART |
| IPC 机制 | D-Bus、Socket、管道 | Binder(内核驱动实现的高性能 IPC) |
| 设备驱动访问 | 用户空间直接 open /dev 节点 | 通过 HAL 封装,框架层不直接访问 |
| 电源管理 | 标准 Linux PM(suspend/resume) | Android wakelock + 早期 suspend 机制 |
| 进程管理 | 标准 fork/exec | Zygote 预孵化 + 按需 fork |
| 存储分区 | 传统分区表(/boot, /root, /home) | system、vendor、product、data 动态分区 |
| 显示系统 | DRM/KMS + Wayland/X11 | SurfaceFlinger + HWC (Hardware Composer) |
| 安全模型 | DAC(传统 Unix 权限) | DAC + MAC(SELinux 强制访问控制) |
| 内核特有驱动 | 标准主线内核 | Binder、ashmem、ion、wakelock(部分已合入主线) |
1.3.1 驱动开发者需要关注的 Android 特有机制
- Binder 驱动:Android 的核心 IPC,驱动位于
drivers/android/binder.c。所有跨进程通信(ServiceManager、AMS、WMS)都依赖它。 - Ion 内存分配器:用于连续/非连续物理内存分配,是 Camera、GPU、Display 驱动的基础。
- Ashmem:匿名共享内存,用于进程间大数据传递(已逐渐被 ION 替代)。
- Wakelock:防止系统进入深度睡眠,驱动中需要正确管理 wakelock 以避免功耗问题。
- HAL 接口:每个硬件模块(Camera、Audio、Sensors)都有对应的 HAL 接口定义(.hal 文件),驱动需要实现这些接口。
实战要点: 在 Android 上开发驱动,不能只写内核模块。你需要同时完成:
1) 内核驱动(字符设备、platform driver、中断处理)
2) HAL 实现(hardware/libhardware 或 HIDL/AIDL 服务)
3) SELinux 策略(允许 HAL 进程访问内核节点)
4) 权限配置(AndroidManifest 或权限 XML)
1) 内核驱动(字符设备、platform driver、中断处理)
2) HAL 实现(hardware/libhardware 或 HIDL/AIDL 服务)
3) SELinux 策略(允许 HAL 进程访问内核节点)
4) 权限配置(AndroidManifest 或权限 XML)
1.3.2 Android 内核版本演进
Android 使用长期稳定版(LTS)内核,并在此基础上增加 Android 特有补丁。常见对应关系:
| Android 版本 | 内核基线 | 主要驱动变化 |
|---|---|---|
| Android 9 (Pie) | Linux 4.4 / 4.9 / 4.14 | Treble 架构强制 HAL 独立 |
| Android 10 | Linux 4.9 / 4.14 / 4.19 | Ion 驱动重构,dma-buf 标准化 |
| Android 11 | Linux 4.14 / 4.19 / 5.4 | Binder 增加冻结功能,SELinux 策略收紧 |
| Android 12+ | Linux 5.4 / 5.10 / 5.15 | 通用内核映像 (GKI) 启动,驱动与内核解耦 |
GKI(通用内核映像):从 Android 12 开始,Google 要求设备使用预编译的通用内核,厂商驱动以模块形式加载。这改变了传统的内核 + 驱动一体化编译方式,驱动开发者需要适配模块化接口。
1.4 本章小结
- Linux 内核是宏内核 + 模块化架构,驱动运行在内核空间,需注意安全与稳定性。
- Android 在 Linux 内核之上构建了应用框架、运行时、HAL 三层,驱动通过 HAL 向上提供服务。
- Android 与标准 Linux 在 IPC、电源管理、显示系统、安全模型等方面存在本质差异。
- 驱动开发者需要掌握内核驱动 + HAL + SELinux + 权限配置 的全栈技能。