Android 14 vold 分析(1)启动

1.启动

它是从rc文件中启动的,rc文件是second stage init才会解析的,也就是说vold主要作用做second stage mount,那first stage mount是怎么做的呢,第一阶段实际上直接调用的是fs_mgr进行的mount,fs_mgr_do_mount_one()

system/core/rootdir/init.rc
584 on early-fs
585     # Once metadata has been mounted, we'll need vold to deal with userdata checkpointing
586     start vold
2. vold main()分析 这里省略不中要的代码
cpp 复制代码
65  int main(int argc, char** argv) {
....
74      LOG(DEBUG) << "Detected support for:"   ---> 这里log输出内核支持的文件系统,结果来自/proc/filesystems见2.1
75                 << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
76                 << (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
77                 << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "")
78                 << (android::vold::IsFilesystemSupported("texfat") ? " texfat" : "")
79                 << (android::vold::IsFilesystemSupported("exfat") ? " exfat" : "");
80  
81      VolumeManager* vm;                      ---> vold中两个主要的组件VolumeManager和NetlinkManager
82      NetlinkManager* nm;                     ---> VolumeManager负责volume的管理, NetlinkManager 负责block device uevent的管理
.........  
93      mkdir("/dev/block/vold", 0755);
94  
95      /* For when cryptfs checks and mounts an encrypted filesystem */
96      klog_set_level(6);                  ---> 设置kernel log输出level 默认是KLOG_INFO_LEVEL = 6
97  
98      /* Create our singleton managers */
99      if (!(vm = VolumeManager::Instance())) {    ---> 为 VolumeManager 创建实例
100          LOG(ERROR) << "Unable to create VolumeManager";
101          exit(1);
102      }
103  
104      if (!(nm = NetlinkManager::Instance())) {   ---> 为 NetlinkManager 创建实例
105          LOG(ERROR) << "Unable to create NetlinkManager";
106          exit(1);
107      }
108  
109      if (android::base::GetBoolProperty("vold.debug", false)) { ---> vold.debug可以用来打开log, 用作显示block device uevent的发生
110          vm->setDebug(true);
111      }
112  
113      if (vm->start()) {            --->  VolumeManager 做初始化的操作
114          PLOG(ERROR) << "Unable to start VolumeManager";
115          exit(1);
116      }
117  
118      VoldConfigs configs = {};
119      if (process_config(vm, &configs)) {  --->  获取volume的config信息, 其实config信息解析自fstab中的flags,见2.2
120          PLOG(ERROR) << "Error reading configuration... continuing anyways";
121      }
122  
123      android::hardware::configureRpcThreadpool(1, false /* callerWillJoin */);
124  
125      ATRACE_BEGIN("VoldNativeService::start");  --->  VoldNativeService是Ivold的实现,作为binder server,创建实例并加入到ServiceManager里
126      if (android::vold::VoldNativeService::start() != android::OK) {
127          LOG(ERROR) << "Unable to start VoldNativeService";
128          exit(1);
129      }
130      ATRACE_END();
131  
132      LOG(DEBUG) << "VoldNativeService::start() completed OK";
133  
134      ATRACE_BEGIN("NetlinkManager::start");
135      if (nm->start()) {                --->  NetlinkManager 做初始化的操作
136          PLOG(ERROR) << "Unable to start NetlinkManager";
137          exit(1);
138      }
139      ATRACE_END();
140  
141      // This call should go after listeners are started to avoid
142      // a deadlock between vold and init (see b/34278978 for details)  ---> 从volume的config信息设置property
143      android::base::SetProperty("vold.has_adoptable", configs.has_adoptable ? "1" : "0");
144      android::base::SetProperty("vold.has_quota", configs.has_quota ? "1" : "0");
145      android::base::SetProperty("vold.has_reserved", configs.has_reserved ? "1" : "0");
146      android::base::SetProperty("vold.has_compress", configs.has_compress ? "1" : "0");
147  
148      // Do coldboot here so it won't block booting,
149      // also the cold boot is needed in case we have flash drive
150      // connected before Vold launched
151      coldboot("/sys/block");      ---> 重新触发一下block device uevent和init进程的RegenerateUevents()类似,见2.3
152  
153      ATRACE_END();    
154  
155      android::IPCThreadState::self()->joinThreadPool();  ------> 开启主线程 binder looper
156      LOG(INFO) << "vold shutting down";
157  
158      exit(0);
159  }
2.1 cat proc/filesystems nodev代表vfs, 好多啊 头大 搞那么多VFS我是真的服
    nodev    sysfs
    nodev    tmpfs
    nodev    bdev
    nodev    proc
    nodev    cgroup
    nodev    cgroup2
    nodev    cpuset
    nodev    binfmt_misc
    nodev    configfs
    nodev    debugfs
    nodev    tracefs
    nodev    securityfs
    nodev    sockfs
    nodev    bpf
    nodev    pipefs
    nodev    ramfs
    nodev    devpts
        ext3
        ext2
        ext4
        vfat
        msdos
        exfat
        fuseblk
    nodev    fuse
    nodev    fusectl
    nodev    virtiofs
    nodev    overlay
    nodev    incremental-fs
        f2fs
        erofs
    nodev    selinuxfs
    nodev    binder
    nodev    pstore
    nodev    functionfs
2.2 process_config()
cpp 复制代码
    229  static int process_config(VolumeManager* vm, VoldConfigs* configs) {
    230      ATRACE_NAME("process_config");
    231  
    232      if (!ReadDefaultFstab(&fstab_default)) {  -------> 读取fstab
    233          PLOG(ERROR) << "Failed to open default fstab";
    234          return -1;
    235      }
    236  
    237      /* Loop through entries looking for ones that vold manages */
    238      configs->has_adoptable = false;
    239      configs->has_quota = false;
    240      configs->has_reserved = false;
    241      configs->has_compress = false;
    242      for (auto& entry : fstab_default) {
    243          if (entry.fs_mgr_flags.quota) {
    244              configs->has_quota = true;
    245          }
    246          if (entry.reserved_size > 0) {
    247              configs->has_reserved = true;  --------> userdata分区是有reserved size的,所以你的手机存储满了还是可以运行的
    248          }
    249          if (entry.fs_mgr_flags.fs_compress) {
    250              configs->has_compress = true;
    251          }
    252  
    253          /* Make sure logical partitions have an updated blk_device. */
    254          if (entry.fs_mgr_flags.logical && !fs_mgr_update_logical_partition(&entry) &&
    255              !entry.fs_mgr_flags.no_fail) {
    256              PLOG(FATAL) << "could not find logical partition " << entry.blk_device;
    257          }
    258  
    259          if (entry.mount_point == "/data" && !entry.metadata_key_dir.empty()) {
    260              // Pre-populate userdata dm-devices since the uevents are asynchronous (b/198405417).
    261              android::vold::defaultkey_precreate_dm_device();  ------> 这个好像有点内容,我还没看
    262          }
    263  
    264          if (entry.fs_mgr_flags.vold_managed) {  ----> 就两个 /storage/sdcard1  /storage/usbotg  wait,voldmanaged=sdcard1:auto
    265              if (entry.fs_mgr_flags.nonremovable) {
    266                  LOG(WARNING) << "nonremovable no longer supported; ignoring volume";
    267                  continue;
    268              }
    269  
    270              std::string sysPattern(entry.blk_device);
    271              std::string nickname(entry.label);
    272              int flags = 0;
    273  
    274              if (entry.is_encryptable()) {
    275                  flags |= android::vold::Disk::Flags::kAdoptable;   ----> sdcard 作为adoptable storage, 能卡死..呵呵..笑了
    276                  configs->has_adoptable = true;
    277              }
    278              if (entry.fs_mgr_flags.no_emulated_sd ||
    279                  android::base::GetBoolProperty("vold.debug.default_primary", false)) {
    280                  flags |= android::vold::Disk::Flags::kDefaultPrimary;
    281              }
    282  
    283              vm->addDiskSource(std::shared_ptr<VolumeManager::DiskSource>( ----> 申明voldmanaged的这俩,被vm添加到了mDisksource
    284                  new VolumeManager::DiskSource(sysPattern, nickname, flags)));
    285          }
    286      }
    287      return 0;
    288  }
2.3 do_coldboot()
cpp 复制代码
    188  static void do_coldboot(DIR* d, int lvl) {
    189      struct dirent* de;
    190      int dfd, fd;
    191  
    192      dfd = dirfd(d);
    193  
    194      fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC);
    195      if (fd >= 0) {
    196          write(fd, "add\n", 4);  --------> 因为vold启动前就已经有block device add了,所以需要重新触发 add block device uevent
    197          close(fd);
    198      }
    199  
    200      while ((de = readdir(d))) {
    201          DIR* d2;
    202  
    203          if (de->d_name[0] == '.') continue;
    204  
    205          if (de->d_type != DT_DIR && lvl > 0) continue;
    206  
    207          fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
    208          if (fd < 0) continue;
    209  
    210          d2 = fdopendir(fd);  
    211          if (d2 == 0)
    212              close(fd);
    213          else {
    214              do_coldboot(d2, lvl + 1); --------> sys/block/没有找到uevent文件,递归往子目录查找
    215              closedir(d2);
    216          }
    217      }
    218  }
相关推荐
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX3 小时前
Android 分区相关介绍
android
大白要努力!4 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee4 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood4 小时前
Perfetto学习大全
android·性能优化·perfetto
Dnelic-7 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen9 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年17 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿19 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神20 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri