>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 19357 个阅读者 刷新本主题
 * 贴子主题:  Android SDCard Mount 流程分析 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-03-31 19:07:43     消息  查看  搜索  好友  邮件  复制  引用

     前段时间对Android 的SDCard unmount 流程进行了几篇简短的分析,由于当时只是纸上谈兵,没有实际上的跟进,可能会有一些误导人或者小错误。今天重新梳理了头绪,针对mount的流程再重新分析一次。    

  本篇大纲

  • android 系统如何开机启动监听mount服务
  • 默认挂载点在Android 系统的哪个目录
  • vold.fstab 配置文件的分析
  • vold 里面启动页面main做了些什么

android 系统如何开机启动监听mount服务

     android sdcard 热插拔监测和执行操作是由一个启动文件vold  所统领的,系统开机会读取初始化配置文件init.rc,该文件位于比如我的板子是:device/ti/omap3evm/init.rc,具体根据自己平台查找。里面有一个是默认启动vold 服务的代码,如下:

     service vold /system/bin/vold

        socket vold stream 0660 root mount

        ioprio be 2

    如果要对该文件做出修改之类,要重新编一下boot.img 镜像文件,烧录进android 系统,之后可以在android的文件系统根目录找到init.rc文件。上述代码为启动vold 启动文件,也可以在init.rc 增加多一些我们想要的文件目录,比如增加一个可以存放多分区挂载的目录等,这个是后话。    

  默认挂载点在Android 系统的哪个目录

      usbdisk 或者 sdcard 热插拔的时候,kernel 会发出命令执行mount或者unmount 操作,但这都是驱动级的。而mount 目录会在android 的文件系统目录下:/dev/block/vold 这个目录由vold 生成,用来存放所有的usbdisk 或者 sdcard 的挂载点。代码位于main里面最优先执行:

         mkdir("/dev/block/vold", 0755) ;  

    可以根据这个目录找到如下节点:

     sh-4.1# ls /dev/block/vold/

    179:0  179:1  8:0    8:1    8:2    8:3    8:4

    节点的小介绍:

         0代表当前的整个设备,1代码当前设备的分区名称代号。

         所以你会发现,sdcard只有一个分区它却生成了两个如:179:0 179:1

         而usbdisk 有四个分区,它会生成五个挂载点:  8:0    8:1    8:2    8:3    8:4  就是这个原因。    

  vold.fstab 配置文件的分析

     vold 里面会通过指定文件来读取预先配置好的sdcard或者多分区配置文件,该文件位于

     /system/core/rootdir/etc/vold.fstab

     如以下的配置文件为:

     dev_mount sdcard /mnt/sdcard auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1

       dev_mount 代表挂载格式

          sdcard 代表挂载的标签

         /mnt/sdcard 代表挂载点

          auto 为自定义选项可以为任何,但必须在main 里面自己判断比如这里的意思为自动挂载

         后面两个目录为设备路径,第一个如果被占用会选择第二个

         配置文件可以根据自己的需要编写,并不是固定的,但最好遵循google vold 启动文件代码的格式编写,要不然会给我们修改代码或者增加多分区功能带来不小的麻烦,如以下我自己编写的多分区挂载支持vold.fstab 配置文件:

    dev_mount sdcard external /mnt/sdcard auto /devices/platform/mmci-omap-hs.0/mmc_host/mmc0 /devices/platform/mmci-omap-hs.0/mmc_host/mmc1

    dev_mount usb1 external /mnt/usbdisk/usb1-disk%d all /devices/platform/ehci-omap.0/usb1/1-2/1-2.1/

    dev_mount usb2 external /mnt/usbdisk/usb2-disk%d all /devices/platform/ehci-omap.0/usb1/1-2/1-2.2/

    dev_mount usb3 external /mnt/usbdisk/usb3-disk%d all /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/

         该文件修改后经系统编译会在android 系统目录里/system/etc/vold.fstab找到。

         /devices/platform/ehci-omap.0/usb1/1-2/1-2.1/  代表要挂载的USB口。

         vold.fstab 只是一个单纯的配置文件,具体的读取和取数据还 是要靠main里面的process_config函数。看代码,里面正有一段用来读取配置文件:

       if (!(fp = fopen("/etc/vold.fstab", "r"))) {

            return -1 ;

        }

             在这个函数里面会根据读取到的数据存放起来,然后满足条件时执行操作。比如代码里面的:

             if (!strcmp(type,  " dev_mount ")) {

                    DirectVolume *dv = NULL;

                   char *part;

                   if (!(part = strtok_r(NULL, delim, &save_ptr))) {

                     SLOGE( " Error parsing partition ");

                     goto out_syntax;

                }

                 if (strcmp(part,  " auto ") && atoi(part) ==  0) {

                    SLOGE( " Partition must either be 'auto' or 1 based index instead of '%s' ", part);

                     goto out_syntax;

                }

                if  (!strcmp(part,  " auto " )) {

                     dv =  new  DirectVolume(vm, label, mount_point, - 1 );

                 }  else  {

                     dv =  new  DirectVolume(vm, label, mount_point, atoi(part));

                 }

                 while ((sysfs_path = strtok_r(NULL, delim, &save_ptr))) {

                     if (*sysfs_path !=  ' / ') {

                         /*  If the first character is not a '/', it must be flags  */

                         break;

                    }

                     if (dv->addPath(sysfs_path)) {

                        SLOGE( " Failed to add devpath %s to volume %s ", sysfs_path,

                             label);

                         goto out_fail;

                    }

                }

                 /*  If sysfs_path is non-null at this point, then it contains

                 * the optional flags for this volume

                  */


                 if (sysfs_path)

                    flags = parse_mount_flags(sysfs_path);

                 else

                    flags =  0;

                dv->setFlags(flags);

                            vm->addVolume(dv);

            }

         DirectVolume后面会讲到,执行mount 和unmount 都是它在做。

         另外,有时后读取配置文件会有问题,这是因为它读取是通过指标下标递增的方式在读,如果有问题可以跟踪打印一下配置文件,看哪里需要修改。        

  vold 里面启动页面main做了些什么

         main 主要是初始化socket 连接监听数据变化,在系统起来时第一时间启动,并且通过读取配置文件来识别usb口或者sdcard 的设备地址,来mount 或者unmount 。其它执行mount 、 unmount  或者删除节点等操作都是由上层或者framework 发送命令给main让其通知volumeManage 执行相应的操作。

                            

----------------------------
原文链接:https://blog.51cto.com/terryblog/826656

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-04-17 12:22:16 重新编辑]
  Java面向对象编程-->类的生命周期
  JavaWeb开发-->使用Session(Ⅰ)
  JSP与Hibernate开发-->Spring、JPA与Hibernate的整合
  Java网络编程-->用Spring整合CXF发布Web服务
  精通Spring-->Vue Router路由管理器
  Vue3开发-->CSS过渡和动画
  Android定义的路径全局变量汇总
  Android自定义组件
  Android线程处理简述
  Android Adapter使用范例
  Android网络编程之WebKit应用
  Android Spinner范例
  ]android:gravity / android:layout_Gravity 的区别
  Android Lint分类及常见错误
  Android Camera2.0 API实现摄像头预览并获取人脸关键坐标
  到底什么是AndroidX?
  Android开发学习笔记:浅谈WebView-IT的点点滴滴
  Flutter 插件开发:以微信SDK为例-Android架构的博客
  MotionLayout 运动布局入门
  Android 之不要滥用 SharedPreferences(上)
  Android - 监听WebView加载失败的处理
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。