Android 14 vold 分析(1)启动

2024-04-10 07:52
文章标签 分析 android 启动 14 vold

本文主要是介绍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()分析 这里省略不中要的代码

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    sysfsnodev    tmpfsnodev    bdevnodev    procnodev    cgroupnodev    cgroup2nodev    cpusetnodev    binfmt_miscnodev    configfsnodev    debugfsnodev    tracefsnodev    securityfsnodev    sockfsnodev    bpfnodev    pipefsnodev    ramfsnodev    devptsext3ext2ext4vfatmsdosexfatfuseblknodev    fusenodev    fusectlnodev    virtiofsnodev    overlaynodev    incremental-fsf2fserofsnodev    selinuxfsnodev    bindernodev    pstorenodev    functionfs

    2.2 process_config()
    229  static int process_config(VolumeManager* vm, VoldConfigs* configs) {230      ATRACE_NAME("process_config");231  232      if (!ReadDefaultFstab(&fstab_default)) {  -------> 读取fstab233          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:auto265              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添加到了mDisksource284                  new VolumeManager::DiskSource(sysPattern, nickname, flags)));285          }286      }287      return 0;288  }
    2.3 do_coldboot()
 
    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 uevent197          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  }

这篇关于Android 14 vold 分析(1)启动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890477

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手