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…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
