Android的存储系统(一)

看了很长时间Vold存储模块的相关知识,也死扣了一段时间的Android源码,发现Android存储系统所涉及的函数调用,以及Kernel与上层之间的Socket传输真的是让人头疼,除了需要整理整个架构的原理以外,还要反复看源码,真真的郁闷。

郁闷之余,还是打算把自己看过的经验之贴和参考资料进行整理,以帖子的形式发出来,供码神们参考,有不对的地方请指正,我们互相交流,下面就进入主题。

Android的存储系统主要由:SystemServer进程中的MountService和Vold进程中的VolumeManager组成。

它们管理着系统的存储设备,执行各种操作,如:mount、unmount、format等。

图1 Android存储系统架构图

图2 Android存储系统原理图

【重要组成分析】

1、NetlinkManager

全称是NetlinkManager.cpp位于Android 4.x 源码位置/system/vold/NetlinkManager.cpp。

该类的主要通过引用NetlinkHandler类中的onEvent()方法来接收来自内核的事件消息,NetlinkHandler位于/system/vold/NetlinkHandler.cpp。

2、VolumeManager

全称是VolumeManager.cpp位于Android 4.x源码位置/system/vold/VolumeManager.cpp。该类的主要作用是接收经过NetlinkManager处理过后的事件消息。

因为我们这里是SD的挂载,因此经过NetlinkManager处理过后的消息会分为五种,分别是:block、switch、usb_composite、battery、power_supply。

这里SD卡挂载的事件是block。

3、DirectVolume

位于/system/vold/DirectVolume.cpp。该类的是一个工具类,主要负责对传入的事件进行进一步的处理。

block事件又可以分为:Add、Removed、Change、Noaction这四种。

4、Volume

位于/system/vold/Volume.cpp,该类是负责SD卡挂载的主要类。Volume.cpp主要负责检查SD卡格式,以及对复合要求的SD卡进行挂载,并通过Socket将消息SD卡挂载的消息传递给NativeDaemonConnector。

5、CommandListener

该类位于位于/system/vold/CommandListener.cpp,通过vold socket与NativeDaemonConnector通信。

6、NativeDaemonConnector

该类位于frameworks/base/services/java/com.android.server/NativeDaemonConnector.java。该类用于接收来自Volume.cpp 发来的SD卡挂载消息并向上传递。

7、MountService

位于frameworks/base/services/java/com.android.server/MountService.java。

MountService是一个服务类,该服务是系统服务,提供对外部存储设备的管理、查询等。在外部存储设备状态发生变化的时候,该类会发出相应的通知给上层应用。在Android系统中这是一个非常重要的类。

8、StorageManaer

位于frameworks/base/core/java/andriod/os/storage/StorageManager.java。

在该类的说明中有提到,该类是系统存储服务的接口。在系统设置中,有Storage相关项,同时Setting也注册了该类的监听器。

而StorageManager又将自己的监听器注册到了MountService中,因此该类主要用于上层应用获取SD卡状态。

【SD卡挂载流程】

1、Kernel发出SD卡插入uevent消息。

2、NetlinkHandler::onEvent()接收内核发出的uevent并进行解析。

3、VolumeManager::handleBlockEvent()处理经过第二步处理后的事件。

4、接下来调用DirectVolume::handleBlockEvent()。

在该方法中需要注意亮点:

(1)程序首先会遍历mPath容器,寻找与event对应的sysfs_path是否存在于mPath容器中;

(2)针对event中的action有4种处理方式:Add、Removed、Change、Noaction。

5、经过上一步之后会调用DirectVolume::handleDiskAdded()方法,该方法中会广播disk insert消息。

6、SocketListener::runListener()会接收DirectVolume::handleDiskAdded()广播的消息。该方法主要完成对event中数据的获取,通过Socket。

7、调用FrameworkListener::onDataAvailable()方法处理接收到的消息内容。

8、FrameworkListener::dispatchCommand()该方法用于分发指令。

9、在FrameworkListener::dispatchCommand()方法中,通过runCommand()方法去调用相应的指令。

10、在/system/vold/CommandListener.cpp中有runCommand()的具体实现。在该类中可以找到这个方法:CommandListener::VolumeCmd::runCommand(),从字面意思上来看这个方法就是对Volume分发指令的解析。该方法中会执行“mount”函数:vm>mountVolume(arg[2])。

11、mountVolume(arg[2])在VolumeManager::mountVolume()中实现,在该方法中调用v>mountVol()。

12、mountVol()方法在Volume::mountVol()中实现,该函数是真正的挂载函数。(在该方法中,后续的处理都在该方法中,在Mount过程中会广播相应的消息给上层,通过setState()函数)。

13、setState(Volume::Checking);广播给上层,正在检查SD卡,为挂载做准备。

14、Fat::check();SD卡检查方法,检查SD卡是否是FAT格式。

15、Fat::doMount()挂载SD卡。

至此,SD的挂载已算初步完成,接下来应该将SD卡挂载后的消息发送给上层,在13中也提到过,在挂载以及检查的过程中其实也有发送消息给上层的。

16、MountService的构造函数中会开启监听线程,用于监听来自vold的socket信息。

Thread thread = new Thread(mConnector,VOLD_TAG); thread.start();

17、mConnector是NativeDaemonConnector的对象,NativeDaemonConnector继承了Runnable并Override了run方法。在run方法中通过一个while(true)调用ListenToSocket()方法来实现实时监听。

18、在ListenToSocket()中,首先建立与Vold通信的Socket Server端,然后调用MountService中的onDaemonConnected()方法。

19、onDaemonConnected()方法是在接口INativeDaemonConnectorCallbacks中定义的,MountService实现了该接口并Override了onDaemonConnected()方法。该方法开启一个线程用于更新外置存储设备的状态,主要更新状态的方法也在其中实现。

20、然后回到ListenToSocket中,通过inputStream来获取Vold传递来的event,并存放在队列中。

21、然后这些event会在onDaemonConnected()通过队列的”队列.take()”方法取出。并根据不同的event调用updatePublicVolumeState()方法,在该方法中调用packageManagerService中的updateExteralState()方法来更新存储设备的状态。

22、更新是通过packageHelper.getMountService().finishMediaUpdate()方法来实现的。

23、在updatePublicVolumeState()方法中,更新后会执行如下代码:

bl.mListener.onStorageStateChanged();

在Android源码/packages/apps/Settings/src/com.android.settings.deviceinfo/Memory.java代码中,实现了StorageEventListener 的匿名内部类,并Override了onStorageStateChanged()方法。因此在updatePublicVolumeState()中调用onStorageStateChanged()方法后,Memory.java中也会收到。在Memory.java中收到以后会在Setting界面进行更新,系统设置—存储中会更新SD卡的状态。从而SD卡的挂载从底层到达了上层。

在下一个帖子中我会对Vold模块的源码以及MountService服务进行分析,包括main函数、NetlinkManager、NetlinkHandler、处理block类型的uevent、处理MountService命令、VolumeManager、NativeDaemonConnector等源码,很快就会与大家见面,感谢支持,欢迎交流与指正!

Android 7.0 存储系统—Vold与MountService分析(一)(转 Android 9.0 分析)的更多相关文章

  1. Android 7.0 存储系统—Vold与MountService分析(三)(转 Android 9.0 分析)

    Android的存储系统(三) 回顾:前帖分析了Vold的main()函数和NetlinkManager的函数调用流程,截止到NetlinkHandler的创建和start()调用,本帖继续分析源码 ...

  2. Android 7.0 存储系统—Vold与MountService分析(二)(转 Android 9.0 分析)

    Android的存储系统(二) 回顾:前贴主要分析了Android存储系统的架构和原理图,简要的介绍了整个从Kernel-->Vold-->上层MountService之间的数据传输流程, ...

  3. Activity的绘制流程简单分析(基于android 4.0源码进行分析)

    要明白这个流程,我们还得从第一部开始,大家都知道 在activity里面 setcontentview 调用结束以后 就可以看到程序加载好我们的布局文件了,从而让我们在手机上看到这个画面. 那么我们来 ...

  4. Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

    我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...

  5. Android 核心分析之十三Android GWES之Android窗口管理

    Android GWES之Android窗口管理1基本构架原理 Android的窗口管理是C/S模式的.Android中的Window是表示Top Level等顶级窗口的概念.DecorView是Wi ...

  6. Android内存机制分析1——了解Android堆和栈

    //----------------------------------------------------------------------------------- Android内存机制分析1 ...

  7. Android系统默认Home应用程序(Launcher)的启动过程源代码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个 Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home ...

  8. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共 ...

  9. Android应用程序框架层和系统运行库层日志系统源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6598703 在开发Android应用程序时,少 ...

随机推荐

  1. Wooden Sticks -HZNU寒假集训

    Wooden Sticks There is a pile of n wooden sticks. The length and weight of each stick are known in a ...

  2. php插入mysql中文数据出现乱码

    $con = mysqli_connect(DB_HOST, DB_USER, DB_PWD, $dbname) or die('数据库连接失败'); mysqli_set_charset($con, ...

  3. 分布式配置管理平台XXL-CONF

    <分布式配置管理平台XXL-CONF>      一.简介 1.1 概述 XXL-CONF 是一个分布式配置管理平台,提供统一的配置管理服务.现已开放源代码,开箱即用. 1.2 特性 1. ...

  4. Hello Django

    首先安装Django: 1.cmd界面,输入"pip3 install django" 2.输入"django-admin help",如下图表示安装成功   ...

  5. python捕获异常、处理异常

    https://blog.csdn.net/jmilk/article/details/50047457

  6. Java并发之CountDownLatch工具类

    一.CountDownLatch工具类介绍 CountDownLatch类是Java并发工具常用的四大工具之一,CountDownLatch允许一个或者多个线程等待其他线程完成工作.假设我们有这样的一 ...

  7. MySQL性能调优——锁定机制与锁优化分析

    针对多线程的并发访问,任何一个数据库都有其锁定机制,它的优劣直接关系着数据的一致完整性与数据库系统的高并发处理性能.锁定机制也因此成了各种数据库的核心技术之一.不同数据库存储引擎的锁定机制是不同的,本 ...

  8. 如何通俗的理解spring的控制反转、依赖注入、面向切面编程等等

    之前一直不理解spring的一些基础特性是什么意思,虽然网上的解释也很多,但是由于我比较笨,就是看不懂,知道最近才稍微了解,下面就以通俗讲解的方式记录下来. 前言 假设我是一个没有开店经验的小老板,准 ...

  9. js中给easyUI年份,月份选择下拉框赋值

    sp中定义 js中初始化 //年度下拉框初始化 $("#yearChoose").combobox({    valueField:'year',     textField:'y ...

  10. Spring加载xml配置文件的方式 ApplicationContext

    大家都知道Java读普通文件是通过Basic I/O 中的InputStream.OutStream.Reader.Writer 等实现的.在spring 框架中,它是怎样识别xml这个配置文件的呢? ...