Android 源码学习之init进程

Boot ROM - Boot Read-Only-Memory

在AOSP源码中,system/core/init/main.cpp 里的 main 函数是整个Android用户空间的起点 。它是在Linux内核启动完成后,由内核直接调用的第一个也是唯一一个用户空间进程

具体时机和调用链条如下:

graph TB subgraph A["Linux 内核启动流程 (kernel/init/main.c)"] A1["start_kernel()"] --> A2["arch_call_rest_init()"] A2 --> A3["rest_init()"] A3 --> A4["kernel_init()"] end subgraph B["关键函数说明"] A1 --> B1["内核主入口点
完成核心子系统初始化
内存管理、调度器、中断等"] A2 --> B2["体系结构相关的
rest_init调用点"] A3 --> B3["创建关键内核线程
- 启动kernel_init(PID=1)
- 启动kthreadd(PID=2)
- 进入idle循环"] A4 --> B4["内核初始化线程
准备用户空间环境
最终执行用户空间init进程"] end subgraph C["与Android的关系"] A4 --> C1["通过execve执行
/system/bin/init"] C1 --> C2["Android init进程
system/core/init/main.cpp"] C2 --> C3["main()"] C3 --> C4["FirstStageMain()"] end subgraph D["关键函数说明"] C3 --> D1["init进程代码入口"] end style A fill:#e1f5fe style B fill:#f3e5f5 style C fill:#e8f5e8 style A1 fill:#ffeb3b style A4 fill:#ff9800

调用时机

  1. Linux内核启动:设备上电后,Bootloader会加载Linux内核到内存并启动它。
  2. 内核初始化:内核进行自身的一系列初始化工作,包括驱动、内存管理等。
  3. 挂载根文件系统 :内核挂载初始RAM磁盘(initramfs)或者(在Android中常见的)直接挂载系统分区作为根文件系统。
  4. 启动第一个用户空间进程 :内核在完成所有核心初始化后,会尝试执行一个名为 init 的程序。这个程序的路径是在内核编译时指定的,通常就是根文件系统下的 /init

调用过程

这个调用过程是由内核代码直接写死的,其逻辑大致如下:

  1. 内核入口点 :在内核源码的 init/main.c 中,kernel_init 函数负责启动第一个用户空间进程。
  2. 尝试执行 :内核会尝试执行 /sbin/init/etc/init/bin/init 等路径。
  3. 回退方案 :如果上述路径都失败了,内核会尝试执行 /bin/sh 作为回退。
  4. 在Android中的情况 :在AOSP编译后,生成的 init 可执行文件被直接放置在了根文件系统的根目录下,即 /init。因此,内核会成功找到并执行它。

这个 /init 程序,就是由 system/core/init/ 目录下的源码编译而成的。

main.cpp 中的 main 函数

所以,main 函数的调用时机非常明确:在Linux内核完成自身初始化,并准备将控制权交给用户空间的那一刻,由内核直接调用。

它的执行流程可以简化为:

cpp 复制代码
// system/core/init/main.cpp

int main(int argc, char** argv) {
    // 1. 处理内核命令行参数,例如 `androidboot.selinux=permissive`
    // 2. 创建必要的目录并挂载文件系统 (如 /dev, /proc, /sys 等)
    // 3. 初始化 Kernel Logging (kmsg)
    // 4. 进行第一次阶段初始化 (First Stage Mount) - 主要在 recovery 或 ramdisk 环境中
    // 5. 如果不是在 First Stage,则执行核心的 init 逻辑
    return FirstStageMain(argc, argv); // 或者 SecondStageMain(argv)
}

在现代Android系统中(尤其是使用了动态分区和A/B更新的设备),init的启动被分成了多个阶段:

  • First Stage Init :在内核还挂载着初始 rootfs 时运行,主要负责挂载真正的系统分区、vendor分区等,并为第二阶段的init设置好环境。
  • Second Stage Init :在必要的分区被挂载后,系统会 execv 重新执行位于新系统分区上的 /system/bin/init,进入第二阶段。这个阶段会建立完整的Android运行环境,包括启动属性服务、解析init.rc脚本、启动守护进程、Zygote等。

总结

项目 说明
调用者 Linux 内核
调用时机 内核完成所有内部初始化之后,准备切换到用户空间时
调用方式 内核通过execve 系统调用执行根文件系统中的 /init 程序
程序路径 在设备根文件系统中为/init,在AOSP源码中位于 system/core/init/

因此,init 进程的PID永远是1,它是所有其他用户空间进程的祖先进程。它的 main 函数是Android系统用户空间的绝对起点。

---- 后续讲解FirstStageMain()相关流程----

相关推荐
聆风吟º2 小时前
【Spring Boot 报错已解决】Spring Boot开发避坑指南:Hibernate实体类主键配置详解与异常修复
android·spring boot·hibernate
APP出海3 小时前
Google政策大更新:涉及金融(个人贷款),社交约会与游戏(未成年人相关),健康等所有类别App
android·游戏·金融·产品运营·产品经理
全栈软件开发4 小时前
音频在线剪切助手网页版源码
android·音视频
2501_915909064 小时前
Flutter 应用怎么加固,多工具组合的工程化实战(Flutter 加固/Dart 混淆/IPA 成品加固/Ipa Guard + CI)
android·flutter·ios·ci/cd·小程序·uni-app·iphone
qq_717410014 小时前
添加快速点击设置-关于设备-版本号弹出仿android13彩蛋
android
wanhengidc4 小时前
云手机的网络架构
服务器·网络·游戏·智能手机·架构·云计算
KdanMin4 小时前
Android MediaCodec 硬编解码实战:从Camera预览到H264流与回环渲染
android·开发语言
峰哥的Android进阶之路4 小时前
Android常见的内存性能优化场景解决方案
android·性能优化
清空mega4 小时前
第三章 Android常见界面控件
android·gitee