Android 启动时判断overlay fs是否挂载

2024-08-29 12:12

本文主要是介绍Android 启动时判断overlay fs是否挂载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、背景

Android新版本使用super分区替代原来的system、vendor后,就采用了overlayfs文件系统。这种文件系统在执行adb remount 后,修改system 、vendor分区内容并不是真正存储在原来的位置,而是单独利用super剩余空间或data分区存了一份新的,原来的文件并没有改变。系统使用时判断有overlay的就用新的,没有就是有原文件。具体概念可查看https://www.cnblogs.com/loongson-artc-lyc/p/15981855.html 了解。

这就带来一个问题,调试时使用adb push 更新了需要开机下载的固件,但是开机过程中不是一开始就挂载overlay fs的,这就可能导致加载的还是老的固件。我们需要在kernel中判断何时挂载了overlay fs再去加载固件,就可以解决这个问题。

二、Init阶段overlay fs挂载前后阶段分析

adb remount log

adb remount[libfs_mgr]fs_mgr_do_format: Format /dev/block/dm-5 as 'f2fs'
Using overlayfs for /vendor
Now reboot your device for settings to take effect
remount succeeded

init 启动代码

system/core/init/main.cppint main(int argc, char** argv) {
#if __has_feature(address_sanitizer)__asan_set_error_report_callback(AsanReportCallback);
#endifif (!strcmp(basename(argv[0]), "ueventd")) {return ueventd_main(argc, argv);}if (argc > 1) {if (!strcmp(argv[1], "subcontext")) {android::base::InitLogging(argv, &android::base::KernelLogger);const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();return SubcontextMain(argc, argv, &function_map);}if (!strcmp(argv[1], "selinux_setup")) {return SetupSelinux(argv);}if (!strcmp(argv[1], "second_stage")) {return SecondStageMain(argc, argv);}}return FirstStageMain(argc, argv);
}

 上面函数会执行多次,执行FirstStageMain时会调用DoFirstStageMount跟据fstab挂载物理分区

和overlay fs

system/core/init/first_stage_init.cppint FirstStageMain(int argc, char** argv) {if (REBOOT_BOOTLOADER_ON_PANIC) {InstallRebootSignalHandlers();}boot_clock::time_point start_time = boot_clock::now();....if (access("/force_debuggable", F_OK) == 0) {std::error_code ec;  // to invoke the overloaded copy_file() that won't throw.if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) ||!fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) {LOG(ERROR) << "Failed to setup debug ramdisk";} else {// setenv for second-stage init to read above kDebugRamdisk* files.setenv("INIT_FORCE_DEBUGGABLE", "true", 1);}}if (!DoFirstStageMount()) {LOG(FATAL) << "Failed to mount required partitions early ...";}...}system/core/init/first_stage_mount.cppbool FirstStageMount::DoFirstStageMount() {if (!IsDmLinearEnabled() && fstab_.empty()) {// Nothing to mount.LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";return true;}if (!InitDevices()) return false;if (!MountPartitions()) return false;return true;
}bool FirstStageMount::MountPartitions() {...// If we don't see /system or / in the fstab, then we need to create an root entry for// overlayfs.if (!GetEntryForMountPoint(&fstab_, "/system") && !GetEntryForMountPoint(&fstab_, "/")) {FstabEntry root_entry;if (GetRootEntry(&root_entry)) {fstab_.emplace_back(std::move(root_entry));}}// heads up for instantiating required device(s) for overlayfs logicauto init_devices = [this](std::set<std::string> devices) -> bool {for (auto iter = devices.begin(); iter != devices.end();) {if (android::base::StartsWith(*iter, "/dev/block/dm-")) {if (!block_dev_init_.InitDmDevice(*iter)) {return false;}iter = devices.erase(iter);} else {iter++;}}return InitRequiredDevices(std::move(devices));};...}

执行SecondStageMain会创建/dev/.booting和/dev/__properties__文件

system/core/init/init.cppint SecondStageMain(int argc, char** argv) {...close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));...PropertyInit();//此函数会创建/dev/__properties__...}

 所以只需要我们在init的第二个阶段去加载固件就可以保证overlay fs已挂载,加载的是新的固件。

判断是否处于第二阶段可以判断/dev/.booting或/dev/__properties__是否存在即可。

三、内核增加判断示例

//#define SECOND_INIT_STAGE_FILE "/dev/.booting" //this file will be deleted when firmware load
#define SECOND_INIT_STAGE_FILE "/dev/__properties__" //this is a dir created at second initfile = filp_open(SECOND_INIT_STAGE_FILE, O_RDONLY, 0);
if (IS_ERR(file)){dev_info(sdev->dev, "%s: open '%s' failed, ret %d\n",__func__, SECOND_INIT_STAGE_FILE, ret);} else {filp_close(file,NULL);
}或bool folder_exists(struct path *path, const char *name) {struct path lookup_path = *path; // 初始路径struct qstr qname = QSTR_INIT(name, strlen(name));int err = path_lookupat(lookup_path.dentry, lookup_path.mnt, qname, &lookup_path);if (err == 0) {// 文件夹存在path_put(&lookup_path); // 释放路径return true;}return false; // 文件夹不存在
}或error = vfs_stat(path,&stat)if(error) {return -ENOENT;//路径不存在
}
if(S_ISDIR(stat.mode)){//是目录
}
else if(S_ISREG(stat.mode)) {//是文件
}else {//其他类型
}

参考:Android 动态分区详解(七) overlayfs 与 adb remount 操作_android overlayfs-CSDN博客

android 系统相关_android super分区-CSDN博客

这篇关于Android 启动时判断overlay fs是否挂载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117823

相关文章

Python如何精准判断某个进程是否在运行

《Python如何精准判断某个进程是否在运行》这篇文章主要为大家详细介绍了Python如何精准判断某个进程是否在运行,本文为大家整理了3种方法并进行了对比,有需要的小伙伴可以跟随小编一起学习一下... 目录一、为什么需要判断进程是否存在二、方法1:用psutil库(推荐)三、方法2:用os.system调用

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Python实现特殊字符判断并去掉非字母和数字的特殊字符

《Python实现特殊字符判断并去掉非字母和数字的特殊字符》在Python中,可以通过多种方法来判断字符串中是否包含非字母、数字的特殊字符,并将这些特殊字符去掉,本文为大家整理了一些常用的,希望对大家... 目录1. 使用正则表达式判断字符串中是否包含特殊字符去掉字符串中的特殊字符2. 使用 str.isa

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Android Mainline基础简介

《AndroidMainline基础简介》AndroidMainline是通过模块化更新Android核心组件的框架,可能提高安全性,本文给大家介绍AndroidMainline基础简介,感兴趣的朋... 目录关键要点什么是 android Mainline?Android Mainline 的工作原理关键

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle