当前位置: 首页 > news >正文

Android守护进程——Vold (Volume Daemon)

简介

介绍:Vold 是用来管理 android 系统的存储设备,如U盘、SD卡、磁盘等移动设备的热插拔、挂载、卸载、格式化

框架结构:Vold 在系统中以守护进程存在,是一个单独的进程。处于Kernel和Framework之间,是两个层级连接的桥梁。下图是Vold在Android系统的整体架构
在这里插入图片描述

组成

重要模块

NetLinkManager(简称NM):内部建立了 socket 连接,主要作用是接收来自 Kernel 的 Uevent 消息。例如SD卡的插拔等动作都会引起 Kernel 向 NM 发送 Uevent 消息
NetlinkHandler:负责解析内核的 Uevent ,它本质上是一个SocketListener类,它们的继承关系,即:NetlinkHandler、NetlinkListener和SocketListener继承关系如下:

VolumeManager模块(简称VM):Android13 中是VM处理完从NM接收到的NetlinkEvent后,通过binder将消息传递给StorageManagerService 进行下一步处理,然后 VM 根据 StorageManagerService 返回的消息管理卷
VoldNativeService模块:主要是与 StorageManagerService 进行通信,继承 BinderService 类,启动过程中主要注册了接口,使其他服务可以通过IVold可以找到,然后启动线程
StorageManager 模块:Framework 层的API,用于APP和其它系统组件访问存储相关的功能。它是 StorageManagerService 的客户端,通过 Binder 调用 StorageManagerService 提供的 API

Vold 启动流程

与其说是Vold启动流程,更不如说是Android存储的初始化工作,Vold的主要功能,就是存储区的管理。Android 的初始化工作可以大致分为三个阶段:

  • 清理环境,因为Android是支持多用户的,启动时的可能是另一个用户,所以需要把之前的用户数据清理干净
  • 启动存储服务,如Vold、StorageManager等等
  • 挂载emulated存储(用于模拟SD卡,历史原因,下面章节会着重介绍)

第一个用户态进程init
• init.rc 启动 Vold 进程

//init.rc  片段
service vold /system/bin/vold \
--blkid_context =u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
--fsck_context =u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
class core
ioprio be 2
task_profiles ProcessCapacityHigh
shutdown critical
group root reserved_disk
reboot_on_failure reboot,vold-failed
// adb shell -> ps -A | grep vold
130|shenoo:/mnt/media_rw # ps -A | grep vold // vold 的父进程PID=1(init)
root           471     1 11001604  9596 binder_wait_for_work 0 S vold

Vold 启动

在这里插入图片描述
动VolumeManager:

  1. VM 会先卸载掉对应文件夹中的所有东西,使之处于一个干净的状态;
  2. 通过VolumeBase基类智能指针new了一个EmulatedVolume对象,同时构造出内置存储目录(/data/media);
  3. 在create函数中,执行了doCreate,doCreate是虚函数,在EmulatedVolume中并没有实现,所以最终还是调用了基类函数,也就直接返回了。之后的listener则是StorageManager服务,但是由于Vold启动较早,SystemServer还没有启动StorageManager,所以这里getListener()得到的是空,后面StorageManager启动完成后会重新触发。
  4. 设置了当前存储设备的状态为unmounted。
  5. 最后Vold会创建一个虚拟磁盘

• 启动VoldNativeService:VoldNativeService依赖的是aidl接口逻辑,连接着StorageManager和vold。它继承自BinderService,启动过程中主要注册了接口,使其他服务可以通过 IVold 可以找到,然后启动线程。
• 启动NetlinkManager:启动过程中内部建立了一个socket连接,用于接收所有的uevent事件,最后会new一个NetlinkHandler对象,并执行start函数。然后调用NetlinkListener父类的startListener函数去监听event。
• 总之,Vold启动完成后,后续Vold会监听kernel的uevent事件,然后处理转发通过Callback通知到StorageManager,而Framework的服务以及App则可以通过StorageManager去使用Vold处理Command

int main(int argc, char** argv) {... //忽略部分代码ATRACE_BEGIN("main");VolumeManager* vm;NetlinkManager* nm;parse_args(argc, argv); //解析传递的参数...mkdir("/dev/block/vold", 0755);...    //创建 VolumeManager 实例if (!(vm = VolumeManager::Instance())) {LOG(ERROR) << "Unable to create VolumeManager";exit(1);}//创建 NetlinkManager 实例if (!(nm = NetlinkManager::Instance())) {LOG(ERROR) << "Unable to create NetlinkManager";exit(1);}if (android::base::GetBoolProperty("vold.debug", false)) {vm->setDebug(true);}//启动 VolumeManagerif (vm->start()) {PLOG(ERROR) << "Unable to start VolumeManager";exit(1);}...VoldConfigs configs = {};if (process_config(vm, &configs)) {PLOG(ERROR) << "Error reading configuration... continuing anyways";}...android::hardware::configureRpcThreadpool(1, false /* callerWillJoin */);...//VoldNativeService它是一个binder服务,start方法会把它发布到ServiceManager中if (android::vold::VoldNativeService::start() != android::OK) {LOG(ERROR) << "Unable to start VoldNativeService";exit(1);}...//启动 NetlinkManagerif (nm->start()) {PLOG(ERROR) << "Unable to start NetlinkManager";exit(1);}...android::IPCThreadState::self()->joinThreadPool();//加入线程池LOG(INFO) << "vold shutting down";exit(0);
}

启动 storaged 服务
此外,系统还会启动与Vold息息相关的服务,比如它的上游服务——StorageManagerService,大致流程如下:

init.rc  ->  Zygote  ->  SystemServer  ->  StorageManagerService

具体:
• 开机后,安卓启动的第一个用户态进程是init,init进程会fork出zygote进程,zygote又fork出 system server
zygote fork system server

 zygoteServer = new ZygoteServer(isPrimaryZygote);

• SystemServer 启动函数入口
zygote 启动服务

     /*** The main entry point from zygote.*/public static void main(String[] args) {new SystemServer().run();}
•	SystemServer().run()会启动各种service

通过 run() 启动各种服务

779      private void run() {.......
955          // Start services.
956          try {
957              t.traceBegin("StartServices");
958              startBootstrapServices(t);.....
962          } catch (Throwable ex) {
963              Slog.e("System", "******************************************");
964              Slog.e("System", "************ Failure starting system services", ex);
965              throw ex;
966          }........

• 在startBootstrapServices函数里会启动 ActivityManager
StartActivityManager

1073      private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {.......
1144          t.traceBegin("StartActivityManager");
1145          // TODO: Might need to move after migration to WM.
1146          ActivityTaskManagerService atm = mSystemServiceManager.startService(
1147                  ActivityTaskManagerService.Lifecycle.class).getService();
1148          mActivityManagerService = ActivityManagerService.Lifecycle.startService(
1149                  mSystemServiceManager, atm);
1150          mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
1151          mActivityManagerService.setInstaller(installer);
1152          mWindowManagerGlobalLock = atm.getGlobalLock();
1153          t.traceEnd();

启动systemReady()函数

 2829          // We now tell the activity manager it is okay to run third party
2830          // code.  It will call back into us once it has gotten to the state
2831          // where third party code can really run (but before it has actually
2832          // started launching the initial applications), for us to complete our
2833          // initialization.
2834          mActivityManagerService.systemReady(() -> {
2835              Slog.i(TAG, "Making services ready");
2836              t.traceBegin("StartActivityManagerReadyPhase");
2837              mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
2838              t.traceEnd();
2839              t.traceBegin("StartObservingNativeCrashes");

systemReady 实现

8264      /**
8265       * Ready. Set. Go!
8266       */
8267      public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
8268          t.traceBegin("PhaseActivityManagerReady");
8269          mSystemServiceManager.preSystemReady();
8392          // On Automotive / Headless System User Mode, at this point the system user has already been
8393          // started and unlocked, and some of the tasks we do here have already been done. So skip
8394          // those in that case. The duplicate system user start is guarded in SystemServiceManager.
8395          // TODO(b/242195409): this workaround shouldn't be necessary once we move the headless-user
8396          // start logic to UserManager-land.
8397          mSystemServiceManager.onUserStarting(t, currentUserId);

处理 H_BOOT_COMPLETED 消息

在这里插入图片描述

相关文章:

  • C# 检查字符串是否包含在另一个字符串中
  • 集合框架--Set集合详解
  • rocketMQ 常见问题记录
  • 使用最新threejs复刻经典贪吃蛇游戏的3D版,附完整源码
  • [Java · 初窥门径] Java 语言初识
  • 拉取windows的docker镜像转到服务器上构建服务镜像
  • 裸金属服务器的应用场景有哪些?
  • 深度学习| Deep Snake环境配置+训练+预测评估(超全面)
  • 如何快速安装和使用AI数字人?AIStarter详细教程与操作指南
  • 【工具】gtest
  • Spring数据访问全解析:ORM整合与JDBC高效实践
  • 楼梯上下检测数据集VOC+YOLO格式5462张2类别
  • 【国家能源集团生态协作平台-注册/登录安全分析报告】
  • 【疑难杂症】【VS Code】VS Code连接不上远程服务器
  • [TriCore][TC3XX][用户手册] - 16.中断控制器 - IR
  • 计算机视觉——基于使用 OpenCV 与 Python 实现相机标定畸变校正
  • C++数据收发管道:构建高效的数据传输通道
  • 【天外之物】概念区分:磅(力)与磅(质量)
  • mysql8.0 创建全文索引及mysql 8.0.32创建全文索引报错 Duplicate entry null-null的解决方案
  • 从数据质量看起,数据治理在做什么?
  • 2025年度“沪惠保”将于4月22日开售,保费不变
  • 上海召开全市加强社会治安综合治理中心规范化建设工作推进会
  • 多米尼加俱乐部屋顶坍塌事故死亡人数升至232人
  • 北京航空航天大学强基计划今年新增4个招生培养方向
  • 以创作呈现意义,初中生在“国宝探索记”中探寻自我与世界
  • 新高!足金饰品报价每克破千元