AOSP 8.0 系统启动之二init启动(一)

本文详细介绍了Android系统中init进程的第一阶段,包括挂载文件系统、初始化日志、启用SELinux安全策略等关键步骤。通过分析init.cpp中的源码,解释了如设置umask、创建目录、挂载各种文件系统(如tmpfs、devpts、proc、sysfs、selinuxfs)以及创建设备节点等操作。在第一阶段结束后,init进程会重新执行自身进入第二阶段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、前言

二、源码分析


一、前言

它的源码在platform/system/core/init/init.cpp。
之前我们讲过init进程是用户空间的第一个进程,我们熟悉的app应用程序都是以它为父进程的,
init进程入口函数是main函数,这个函数做的事情还是比较多的,主要分为三个部分

  • init进程第一阶段
  • init进程第二阶段
  • init.rc文件解析

由于内容比较多,所以对于init的讲解,计划分为三个章节来讲,本文只讲解第一阶段,第一阶段主要有以下内容

  • 挂载文件系统并创建目录
  • 初始化日志输出、挂载分区设备
  • 启用SELinux安全策略
  • 开始第二阶段前的准备

本文涉及到的文件

platform/system/core/init/init.cpp
platform/system/core/init/ueventd.cpp
platform/system/core/init/watchdogd.cpp
platform/system/core/init/log.cpp
platform/system/core/base/logging.cpp
platform/system/core/init/init_first_stage.cpp
platform/external/selinux/libselinux/src/callbacks.c
platform/external/selinux/libselinux/src/load_policy.c
platform/external/selinux/libselinux/src/getenforce.c
platform/external/selinux/libselinux/src/setenforce.c
platform/external/selinux/libselinux/src/android/android.c

二、源码分析

init.cpp 

int main(int argc, char** argv) {
    
    //在编译为:userdebug 和 eng 版本的固件中,会打开该选项。线上user版本是不会打开的;
    if (REBOOT_BOOTLOADER_ON_PANIC) { //定义在system/core/init/Android.mk之中,
        InstallRebootSignalHandlers();
    }
    
    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    //判断是否为开机第一次启动
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();
     
        // Clear the umask.
        umask(0); // 设置 umask 值为0,清空访问权限屏蔽码
     
        // Get the basic filesystem setup we need put together in the initramdisk
        // on / and then we'll let the rc file figure out the rest.
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        #define MAKE_STR(x) __STRING(x)
        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
        // Don't expose the raw commandline to unprivileged processes.
        chmod("/proc/cmdline", 0440);
        gid_t groups[] = { AID_READPROC };
        setgroups(arraysize(groups), groups);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
        ...
        InitKernelLogging(argv); //往proc/kmsg节点写日志
     
        setenv("INIT_SECOND_STAGE", "true", 1);
        ...
        char* path = argv[0]; 
        char* args[] = { path, nullptr };
        execv(path, args);  //重新执行init进程,会重新执行main 函数
    }
}

接下去重点分析init启动的第二阶段;

<think>首先,用户的问题是关于在AOSP源码环境中配置JDK版本。用户问:“如何在AOSP源码中设置或修改JDK版本”。 我需要基于系统级指令来回答: - 所有行内数学表达式必须使用$...$格式,但在这个上下文中,可能没有数学表达式,所以我可以忽略。 - 独立公式必须使用$$...$$格式并单独成段,同样可能不适用。 - LaTeX语法正确:确保任何公式都正确。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答后,添加相关问题部分。 - 回答中引用的段落末尾自然地添加引用标识:例如[^1]。我需要引用提供的引用内容。 用户提供的引用: - [^1]: 关于阅读AOSP源码的目录结构和重要性。 - [^2]: 关于在Ubuntu 14.04下搭建AOSP编译环境,包括软件依赖。 - [^3]: 记录编译AOSP和修改源码,提到安装JDK8。 - [^4]: 更新库的命令。 - [^5]: 关于Android Studio导入AOSP源码时排除目录。 用户的问题聚焦在设置或修改JDK版本。从引用中,[^3]提到安装JDK8,这表明在AOSP编译中,JDK版本很重要。 我的回答需要: - 结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠:基于AOSP的知识,JDK版本在编译AOSP时是关键的,因为不同版本的AOSP需要不同的JDK版本。例如,Android 6.0需要JDK 7或8,而更新的版本如Android 10需要JDK 8或更高。 关键点: - 在AOSP中,JDK版本通常通过环境变量或构建脚本设置。 - 常见的设置是修改环境变量JAVA_HOME。 - 在编译脚本中,如build/envsetup.sh或build/core/main.mk,可能会有JDK版本检查。 - 用户需要确保安装正确的JDK版本,并设置路径。 步骤: 1. **检查当前JDK版本**:使用命令如 `java -version` 和 `javac -version`。 2. **安装所需JDK版本**:根据AOSP版本选择JDK。例如,对于Android 10,需要JDK 8。 3. **设置环境变量**:设置JAVA_HOME指向JDK安装目录,并添加bin目录到PATH。 4. **在AOSP构建中配置**:AOSP构建系统可能自动检测JDK,但有时需要手动设置。 5. **验证设置**:在编译前运行相关命令检查。 从引用[^3]:“安装JDK8”,这暗示在Android 10源码编译中需要JDK8。 在回答中,我需要引用相关部分: - 例如,提到编译环境时,引用[^2]或[^3]。 回答结构: - 引言:解释为什么需要设置JDK版本。 - 步骤:逐步指导如何设置。 - 结尾:确认设置后编译。 - 相关问题:生成相关问题。 相关问题想法: 1. 如何检查AOSP编译所需的JDK版本? 2. 如果JDK版本不匹配,编译AOSP时会出现什么错误? 3. 如何在Ubuntu系统上安装多个JDK版本并切换? 4. AOSP编译中JDK版本的选择如何影响最终构建? 确保回答真实可靠:基于AOSP文档和常见实践。 最终回答用中文。</think>### 在AOSP源码中设置或修改JDK版本 在Android Open Source Project (AOSP) 源码环境中,JDK版本的选择至关重要,因为不同版本的AOSP(如Android 10Android 12)需要特定版本的JDK来确保编译成功。如果JDK版本不匹配,编译过程可能失败,出现错误如“unsupported major.minor version”。以下我将逐步指导您如何设置或修改JDK版本,确保编译环境正确配置。整个过程基于AOSP标准实践和引用内容,分为环境准备、JDK安装、变量设置和验证步骤。 #### 步骤1: 确认AOSP版本所需的JDK版本 在开始前,请先检查您的AOSP源码版本,因为不同版本有特定JDK要求: - 对于Android 6.0(Marshmallow)及更早版本,通常需要JDK 7。 - 对于Android 7.0(Nougat)到Android 8.0(Oreo),推荐JDK 8。 - 对于Android 9.0(Pie)及更高版本(如Android 10或12),必须使用JDK 8或更高(某些版本可能需要JDK 11)。 - 参考AOSP官方文档或构建脚本,如`build/core/main.mk`,其中会指定JDK版本要求[^3]。 您可以通过以下命令快速查看AOSP版本: ```bash cd ~/aosp # 进入AOSP源码根目录 cat build/core/version_defaults.mk | grep "PLATFORM_VERSION" ``` #### 步骤2: 安装所需的JDK版本 根据步骤1的结果,安装正确的JDK版本。在Ubuntu系统上,推荐使用OpenJDK。以下以安装JDK 8为例(适用于大多数现代AOSP版本): - 安装OpenJDK 8: ```bash sudo apt update sudo apt install openjdk-8-jdk # 安装JDK 8 ``` - 如果需要其他版本(如JDK 11),可替换为`openjdk-11-jdk`。 - 安装后,验证版本: ```bash java -version # 应显示"openjdk version "1.8.x" javac -version # 应显示"javac 1.8.x" ``` 如果系统中已安装多个JDK,可使用`update-alternatives`切换(详见相关问题部分)[^3]。 #### 步骤3: 设置环境变量 AOSP构建系统(如通过`make`或`m`命令)依赖环境变量`JAVA_HOME`来定位JDK。设置步骤如下: - 打开终端,编辑您的shell配置文件(如`~/.bashrc`或`~/.zshrc`): ```bash nano ~/.bashrc # 使用nano编辑器,或替换为vim ``` - 在文件末尾添加以下行,将`JAVA_HOME`指向JDK安装路径(通常为`/usr/lib/jvm/java-8-openjdk-amd64`,但需根据实际路径调整): ```bash export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 # JDK 8的默认路径 export PATH=$JAVA_HOME/bin:$PATH ``` - 保存文件后,应用更改: ```bash source ~/.bashrc ``` - 验证变量设置: ```bash echo $JAVA_HOME # 应输出JDK路径 which java # 应指向$JAVA_HOME/bin/java ``` 此步骤确保AOSP构建脚本能自动检测JDK版本。环境变量的设置是编译前准备的关键部分,类似于引用中提到的源码工作环境配置[^2]。 #### 步骤4: 在AOSP构建中验证和编译 设置完成后,在AOSP源码根目录下进行验证: - 运行AOSP的环境设置脚本: ```bash source build/envsetup.sh # 初始化构建环境 lunch aosp_arm-eng # 选择目标设备(例如aosp_arm-eng) ``` - 检查JDK版本是否被正确识别: ```bash make -j4 showcommands 2>&1 | grep "JAVA_HOME" # 应输出设置的JDK路径 ``` - 如果切正常,开始编译: ```bash make -j4 # 使用4个线程编译,根据CPU核心数调整 ``` 如果JDK版本设置正确,编译将顺利进行。如果出现错误(如JDK版本不兼容),请根据错误信息回退到步骤1重新确认版本。 #### 注意事项 - **JDK版本冲突**:如果系统中有多个JDK,确保`JAVA_HOME`指向正确的版本。编译失败时,错误日志通常会提示所需JDK版本。 - **AOSP版本兼容性**:对于较新AOSP版本(如Android 12),可能需要JDK 11。您可以在`build/soong/java/config.go`文件中检查具体要求。 - **环境隔离**:推荐在Docker容器或虚拟机中设置AOSP环境,避免系统级JDK冲突。引用中提到源码工作环境的准备包括依赖库安装,这能减少问题[^2]。 - **源码修改**:在极少数情况下,如果您需要修改AOSP构建脚本来强制JDK版本(例如在`build/core/main.mk`中添加`REQUIRED_JAVA_VERSION := 1.8`),但通常环境变量设置已足够。 通过以上步骤,您应该能成功在AOSP源码中设置JDK版本。如果在编译中遇到问题,请提供错误日志以便进步诊断。 ### 相关问题 1. **如何检查AOSP编译所需的JDK版本?** (这涉及解析AOSP构建脚本或官方文档。) 2. **如果JDK版本不匹配,编译AOSP时会出现什么常见错误?如何解决?** (例如,处理“unsupported class file version”错误。) 3. **如何在Ubuntu系统上安装并切换多个JDK版本?** (使用`update-alternatives`工具管理多个JDK。) 4. **AOSP编译中,JDK版本的选择如何影响最终构建的APK或系统镜像?** (讨论兼容性和性能优化。) 5. **在Android Studio中导入AOSP源码时,如何避免JDK版本冲突?** (引用中提到排除目录的方法,可扩展到JDK设置[^5]。) [^1]: 本文将引导读者阅读AOSP源码,并熟悉其目录结构。通过本文的介绍,读者可以掌握阅读AOSP源码的方法,熟悉其目录结构,并深入了解某个AOSP项目的代码。希望读者能够在实践中不断提高自己的技能和探索能力。 二、为什么要阅读AOSP源码? [^2]: 源码工作环境, 就是安装所依赖的些软件库, 以及开发调试时需要进行的些配置。 主要分为编译环境准备, AOSP源码下载, 源码预编译等。 这里主要介绍在Ubuntu14.04 LTS下开发Android6.0代码的工作环境准备。 编译环境搭建( Ubuntu14.04) [^3]: 记录编译aosp+修改源码。PLAINTEXT 1 2 3 4 cd ~/bin/aosp/.repo/repo git pull cd ~/bin/aosp 再次repo init 和 repo sync android10源码的编译 1、安装JDK8 [^4]: 也可以更新库 repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-security-12.0.0_r47 repo sync [^5]: AndroidStudio导入Android AOSP源码。打开android.iml文件看看,默认把几乎所有的源码都导入了,只有几个文件夹被排除在外,工程将会非常大,而且会很耗时间。 然而我们并不关心这么多的源码,我们可以自己加excludeFolder标签,把自己不关心的目录写在这里,告诉AndroidStudio不要导入这个目录下的源码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值