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…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...