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

Android的存储系统(一)java

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

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

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

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

图1 Android存储系统架构图ide

图2 Android存储系统原理图函数

【重要组成分析】工具

一、NetlinkManagerspa

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

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

二、VolumeManager

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

     由于咱们这里是SD的挂载,所以通过NetlinkManager处理事后的消息会分为五种,分别是:block、switch、usb_composite、battery、power_supply。

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

三、DirectVolume

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

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

四、Volume

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

五、CommandListener

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

六、NativeDaemonConnector

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

七、MountService

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

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

八、StorageManaer

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

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

     而StorageManager又将本身的监听器注册到了MountService中,所以该类主要用于上层应用获取SD卡状态。

 

【SD卡挂载流程】

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

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

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

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

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

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

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

 

 

 

 

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

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

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

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

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

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

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

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

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

1四、Fat::check();SD卡检查方法,检查SD卡是不是FAT格式。

1五、Fat::doMount()挂载SD卡。

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

 

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

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

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

1八、在ListenToSocket()中,首先创建与Vold通讯的Socket Server端,而后调用MountService中的onDaemonConnected()方法。

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

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

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

2二、更新是经过packageHelper.getMountService().finishMediaUpdate()方法来实现的。

2三、在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等源码,很快就会与你们见面,感谢支持,欢迎交流与指正!
相关文章
相关标签/搜索