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. 简述Action+Service +Dao 功能

    转载:http://blog.csdn.net/inter_peng/article/details/41021727 1. Action/Service/DAO简介: Action是管理业务(Ser ...

  2. 搭建centos7的开发环境2-单机版Hadoop2.7.3配置

    最近公司准备升级spark环境,主要原因是生产环境的spark和hadoop版本都比较低,但是具体升级到何种版本还不确定,需要做进一步的测试分析.这个任务对于大数据开发环境配置有要求,这里记录一下配置 ...

  3. HTML 学习笔记 day three

    HTML学习笔记 Day three 7.2插入多媒体元素 插入音乐 语法结构:<embed  src=”音乐文件的路径”></embed> 属性: Autostart:他只有 ...

  4. Java基础:内存模型

    1. 引言 2. Java内存模型 3. 内存间的交互操作 1. 引言 考虑到计算机组成的内容: 原始的计算机是CPU用于计算+硬盘用于存储,由于CPU的高速发展和硬盘的缓慢发展,高速的存储需要持续供 ...

  5. Robot Framework自动化_Selenium2Library 关键字

    Robot Framework自动化_Selenium2Library 关键字 培训老师:肖能尤 2016/06/12 课程目的 一.Robot framework Selenium2Library ...

  6. webpack4 splitChunksPlugin && runtimeChunkPlugin 配置杂记

    webpack2 还没研究好,就发现升级到4了,你咋这么快~ 最近要做项目脚手架,项目构建准备重新做,因为之前写的太烂了...然后发现webpack大版本已经升到4了(又去看了一眼,4.5了),这么快 ...

  7. 【机器学习】使用gensim 的 doc2vec 实现文本相似度检测

    环境 Python3, gensim,jieba,numpy ,pandas 原理:文章转成向量,然后在计算两个向量的余弦值. Gensim gensim是一个python的自然语言处理库,能够将文档 ...

  8. css基础--深入理解opacity和rgba的区别

    欢迎访问我的个人博客:http://www.xiaolongwu.cn 前言 首先这两个都与透明度有关,那么他们之间有什么具体的区别呢?在实际工作中我们需要注意什么呢?请您接着往下看 语法 1. rg ...

  9. SSM-Spring-21:Spring中事物的使用案例

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 股票买卖案例(我会用三种开启事物的方法 代理工厂bean版的,注解版的,aspectj xml版的) 简单的介 ...

  10. Linux时间子系统之(十七):ARM generic timer驱动代码分析

    专题文档汇总目录 Notes:ARM平台Clock/Timer架构:System counter.Timer以及两者之间关系:Per cpu timer通过CP15访问,System counter通 ...