Android 14 vold 分析(2)VolumeManager 和 NetlinkManger
3. VolumeManager::Instance() 和 VolumeManager::start()
system/vold/VolumeManager.cpp
3.1 Instance()没啥好说的 非常简单
112 VolumeManager* VolumeManager::Instance() {113 if (!sInstance) sInstance = new VolumeManager();114 return sInstance;115 }116 117 VolumeManager::VolumeManager() {118 mDebug = false;119 mNextObbId = 0;120 mNextStubId = 0;121 // For security reasons, assume that a secure keyguard is122 // showing until we hear otherwise123 mSecureKeyguardShowing = true;124 }
3.2 VolumeManager::start()
174 int VolumeManager::start() {175 ATRACE_NAME("VolumeManager::start");176 177 // Always start from a clean slate by unmounting everything in178 // directories that we own, in case we crashed.179 unmountAll(); -----> 全部 unmount , 这里的unmount似乎并不是全部所有分区, 全部的话那还了得180 181 Loop::destroyAll();182 183 // Assume that we always have an emulated volume on internal184 // storage; the framework will decide if it should be mounted.185 CHECK(mInternalEmulatedVolumes.empty());186 187 auto vol = std::shared_ptr<android::vold::VolumeBase>(188 new android::vold::EmulatedVolume("/data/media", 0)); ---> 创建 EmulatedVolume189 vol->setMountUserId(0);190 vol->create();191 mInternalEmulatedVolumes.push_back(vol);192 193 // Consider creating a virtual disk194 updateVirtualDisk();195 196 return 0;197 }
4. NetlinkManger::Instance() 和 NetlinkManger::start()
system/vold/NetlinkManager.cpp
4.1 NetlinkManger::Instance() 很简单 不需要赘述
36 NetlinkManager* NetlinkManager::Instance() {37 if (!sInstance) sInstance = new NetlinkManager();38 return sInstance;39 }40 41 NetlinkManager::NetlinkManager() {42 mBroadcaster = NULL;43 }
4.2 NetlinkManger::start()
47 int NetlinkManager::start() {48 struct sockaddr_nl nladdr;49 int sz = 64 * 1024;50 int on = 1;51 52 memset(&nladdr, 0, sizeof(nladdr));53 nladdr.nl_family = AF_NETLINK;54 nladdr.nl_pid = getpid();55 nladdr.nl_groups = 0xffffffff;56 57 if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)) < 0) { ---> 创建socket client58 PLOG(ERROR) << "Unable to create uevent socket";59 return -1;60 }61 62 // When running in a net/user namespace, SO_RCVBUFFORCE will fail because63 // it will check for the CAP_NET_ADMIN capability in the root namespace.64 // Try using SO_RCVBUF if that fails.65 if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) &&66 (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) {67 PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option";68 goto out;69 }70 71 if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {72 PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option";73 goto out;74 }75 76 if (bind(mSock, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) { --> socket bind77 PLOG(ERROR) << "Unable to bind uevent socket";78 goto out;79 }80 81 mHandler = new NetlinkHandler(mSock); --> 创建 new NetlinkHandler82 if (mHandler->start()) { --> 创建 new NetlinkHandler.start() 见4.383 PLOG(ERROR) << "Unable to start NetlinkHandler";84 goto out;85 }86 87 return 0;88 89 out:90 close(mSock);91 return -1;92 }
4.3 new NetlinkHandler and start()
这有个继承关系NetlinkHandler : NetlinkListener : SocketListener
2 int NetlinkHandler::start() {33 return this->startListener(); ------> 实际就是SocketListener poll监听,是否有POLLIN 产生, onDataAvailable -> onEvent34 }35 36 void NetlinkHandler::onEvent(NetlinkEvent* evt) { ---> 收到了uevent37 VolumeManager* vm = VolumeManager::Instance();38 const char* subsys = evt->getSubsystem();39 40 if (!subsys) {41 LOG(WARNING) << "No subsystem found in netlink event";42 return;43 }44 45 if (std::string(subsys) == "block") { ------> 只有uevent的subsys是block才会处理的46 vm->handleBlockEvent(evt); ------> VolumeManager处理 block device uevent 见 4.447 }48 }
4.4 VolumeManager::handleBlockEvent()
199 void VolumeManager::handleBlockEvent(NetlinkEvent* evt) {200 std::lock_guard<std::mutex> lock(mLock);201 202 if (mDebug) {203 LOG(DEBUG) << "----------------";204 LOG(DEBUG) << "handleBlockEvent with action " << (int)evt->getAction(); ---> 这里是vold.debug控制的,打印具体的action205 evt->dump();206 }207 208 std::string eventPath(evt->findParam("DEVPATH") ? evt->findParam("DEVPATH") : "");209 std::string devType(evt->findParam("DEVTYPE") ? evt->findParam("DEVTYPE") : "");210 211 if (devType != "disk") return; ---> devType不是disk还不处理, 真是牛逼哄哄212 213 int major = std::stoi(evt->findParam("MAJOR"));214 int minor = std::stoi(evt->findParam("MINOR"));215 dev_t device = makedev(major, minor); ---> 创建block device组合216 217 switch (evt->getAction()) {218 case NetlinkEvent::Action::kAdd: { ---> uevent action为add 具体见4.5219 for (const auto& source : mDiskSources) { ---> 之前添加的两个disksource,还记得吗,只支持sd卡和U盘220 if (source->matches(eventPath)) {221 // For now, assume that MMC and virtio-blk (the latter is222 // specific to virtual platforms; see Utils.cpp for details)223 // devices are SD, and that everything else is USB224 int flags = source->getFlags();225 if (major == kMajorBlockMmc || IsVirtioBlkDevice(major)) {226 flags |= android::vold::Disk::Flags::kSd; ---> SD卡227 } else {228 flags |= android::vold::Disk::Flags::kUsb; ---> usb storage, 通过otg插入的229 }230 231 auto disk =232 new android::vold::Disk(eventPath, device, source->getNickname(), flags); ---> 创建一个disk设备节点mknod233 handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk)); --> 真正的处理234 break;235 }236 }237 break;238 }239 case NetlinkEvent::Action::kChange: { --> uevent action为add 具体见4.6240 LOG(VERBOSE) << "Disk at " << major << ":" << minor << " changed";241 handleDiskChanged(device);242 break;243 }244 case NetlinkEvent::Action::kRemove: { --> uevent action为add 具体见4.7245 handleDiskRemoved(device);246 break;247 }248 default: {249 LOG(WARNING) << "Unexpected block event action " << (int)evt->getAction();250 break;251 }252 }253 }
4.5 new android::vold::Disk()和handleDiskAdded()
system/vold/model/Disk.cpp
4.5.1 new android::vold::Disk()
Disk::Disk(const std::string& eventPath, dev_t device, const std::string& nickname, int flags)95 : mDevice(device),96 mSize(-1),97 mNickname(nickname),98 mFlags(flags),99 mCreated(false),100 mJustPartitioned(false) {101 mId = StringPrintf("disk:%u,%u", major(device), minor(device));102 mEventPath = eventPath;103 mSysPath = StringPrintf("/sys/%s", eventPath.c_str());104 mDevPath = StringPrintf("/dev/block/vold/%s", mId.c_str());105 CreateDeviceNode(mDevPath, mDevice); ---------> 创建block device 的设备节点mknod106 }
4.5.2 handleDiskAdded()
255 void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {256 // For security reasons, if secure keyguard is showing, wait257 // until the user unlocks the device to actually touch it258 // Additionally, wait until user 0 is actually started, since we need259 // the user to be up before we can mount a FUSE daemon to handle the disk.260 bool userZeroStarted = mStartedUsers.find(0) != mStartedUsers.end();261 if (mSecureKeyguardShowing) {262 LOG(INFO) << "Found disk at " << disk->getEventPath()263 << " but delaying scan due to secure keyguard";264 mPendingDisks.push_back(disk);265 } else if (!userZeroStarted) {266 LOG(INFO) << "Found disk at " << disk->getEventPath()267 << " but delaying scan due to user zero not having started";268 mPendingDisks.push_back(disk);269 } else {270 disk->create(); ---------> disk->create()271 mDisks.push_back(disk);272 }273 }146 status_t Disk::create() {147 CHECK(!mCreated);148 mCreated = true;149 150 auto listener = VolumeManager::Instance()->getListener(); ---------> StorageManaerService通信151 if (listener) listener->onDiskCreated(getId(), mFlags); ------> StorageManaerService->onDiskCreated()152 153 if (isStub()) {154 createStubVolume();155 return OK;156 }157 readMetadata(); --------> listener->onDiskMetadataChanged(getId(), mSize, mLabel, mSysPath);158 readPartitions(); --------> Disk::createPublicVolume() listener->onVolumeCreated()and listener->onDiskScanned()159 return OK;160 }
思考, vold比mount service启动的早,那开机时vold获取到的listener为空,也就是说虽然disk创建了但是不会mount,那什么时候才会mount呢? 我们下一篇文章解答
相关文章:
Android 14 vold 分析(2)VolumeManager 和 NetlinkManger
3. VolumeManager::Instance() 和 VolumeManager::start() system/vold/VolumeManager.cpp 3.1 Instance()没啥好说的 非常简单 112 VolumeManager* VolumeManager::Instance() {113 if (!sInstance) sInstance new VolumeManager();114 return sInst…...
《黑马点评》Redis高并发项目实战笔记(上)P1~P45
P1 Redis企业实战课程介绍 P2 短信登录 导入黑马点评项目 首先在数据库连接下新建一个数据库hmdp,然后右键hmdp下的表,选择运行SQL文件,然后指定运行文件hmdp.sql即可(建议MySQL的版本在5.7及以上): 下面这…...
pytorch车牌识别
目录 使用pytorch库中CNN模型进行图像识别收集数据集定义CNN模型卷积层池化层全连接层 CNN模型代码使用模型 使用pytorch库中CNN模型进行图像识别 收集数据集 可以去找开源的数据集或者自己手做一个 最终整合成 类别分类的图片文件 定义CNN模型 卷积层 功能:提…...
【C++入门】内联函数、auto与基于范围的for循环
💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…...
服务器停用,备份服务文件。
文章目录 引言I 文件备份1.1 数据库文件/证书1.2 redis1.3 nacosII JAVA流水线备份2.1 java构建2.2 镜像构建2.3 docker 部署2.4 子模块构建2.5 Dockerfile_prodIII VUE项目流水线备份3.1 Node.js 构建3.2 Dockerfile_prod...
基于Python的深度学习的中文情感分析系统(V2.0),附源码
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
使用Postman发送跨域请求实验
使用Postman发送跨域请求 1 跨域是什么?2 何为同源呢?3 跨域请求是如何被检测到的?4 Postman跨域请求测试4.1 后端准备4.2 测试用例4.2.1 后端未配置跨域请求(1) 前端不跨域(2)前端跨域 4.2.2 后端配置跨域信息(1&…...
4、jvm-垃圾收集算法与垃圾收集器
垃圾收集算法 分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。 比如…...
[Excel]如何限制儲存格輸入格式? 以“字首為英文字母大寫,其餘為數字,共15碼“為範例
[Excel]如何限制儲存格輸入格式 需求: 當一個excel表格需要由多位使用者來輸入資料時,難免會出現資料輸入錯誤問題,尤其是料號,品號或是訂單號的長類型編碼。若是問題屬於輸入錯誤"資料"但格式未錯誤,則可能需要讓exce…...
错题记录-华为海思
华为 海思数字芯片 参考 :FPGA开发/数字IC笔试系列(5) 华为海思IC笔试解析 FPGA开发/数字IC笔试系列(6) 华为海思IC笔试解析 SystemVerilog Function与Task的区别 $readmemh与$readmemb这两个系统任务是用来从指定文件中读取数据到寄存器数组或者RAM、ROM中。除了…...
rspack 使用构建vue3脚手架
基于 Rust 的高性能 Web 构建工具。rspack 主要适配 webpack 生态,对于绝大多数 webpack 工具库都是支持的。 启动速度快;增量热更新快。兼容 webpack 生态;内置了 ts、jsx、css、css modules 等开箱即用。生产优化,tree shaking…...
maven之pom中的build标签
1、build标签分类 1.1、全局配置(project build) 针对整个项目的所有情况都有效。 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"htt…...
Cesium.js--》探秘Cesium背后的3D模型魔力—加载纽约模型
今天简单实现一个Cesium.js的小Demo,加强自己对Cesium知识的掌握与学习,先简单对这个开源库进行一个简单的介绍吧! Cesium 是一个开源的地理空间可视化引擎,用于创建基于 Web 的三维地球应用程序。它允许开发人员在网页上呈现高度…...
.NET i18n 多语言支持与国际化
环境 WIN10 VS2022 .NET8 1.👋创建项目 2.👀创建Resources Controllers HomeController.en.resx HomeController.fr.resx HomeController.zh.resx 3.🌱Program.cs添加国际化支持 // 添加国际化支持 builder.Services.AddLocalization(…...
基于Pytorch实现图像分类——基于jupyter
分类任务 网络基本构建与训练方法,常用函数解torch.nn.functional模块nn.Module模块 MNIST数据集下载 from pathlib import Path import requestsDATA_PATH Path("data") PATH DATA_PATH / "mnist"PATH.mkdir(parentsTrue, exist_okTrue)U…...
如何将CSDN的文章以PDF文件形式保存到本地
1.F12 打开开发者工具窗口 2.console下输入命令 (function(){$("#side").remove();$("#comment_title, #comment_list, #comment_bar, #comment_form, .announce, #ad_cen, #ad_bot").remove();$(".nav_top_2011, #header, #navigator").remove…...
面试经典150题——删除有序数组中的重复项
面试经典150题 day3 题目来源我的题解方法一 双指针 题目来源 力扣每日一题;题序:26 我的题解 方法一 双指针 使用两个指针分别指向相同元素的左右边界,再利用一个count记录最终需要的数组长度。 时间复杂度:O(n) 空间复杂度&a…...
Unity3D知识点精华浓缩
一、细节 1、类与组件的关系 2、Time.deltaTime的含义 3、怎么表示一帧的移动距离 4、Update和LateUpdate的区别和适用场景 5、找游戏对象的方式(别的对象 / 当前对象的子对象) 6、组件1调用组件2中方法的方式 7、在面板中获取外部数据的方法 8、序列化属…...
HTML的文档说明
1.告诉浏览器当前网页的版本 2.写法: !以前的写法:要依据网页的HTML的版本去确定,紫萼发油很多很多。 具体的写法可以参考:W3C官网的文档说明 !新写法:W3C都推荐用h5的写法 <DOCTYPE ht…...
ubuntu 更新或更改GCC/G++
最近遇到一些问题,需要用到gcc-9/g-9,但是我自带的ubuntu18.04是gcc-7.5/g-7.5,所以升级一下,奈何文章太多而且很多无效,所以在此记录一下: 参考:https://stackoverflow.com/questions/19836858…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
