Android2.3.5 vold个人总结

来源:互联网 发布:力士乐plc编程软件 编辑:程序博客网 时间:2024/05/17 03:48


一、相关文件

system/vold/目录下:

CommandListener.h DirectVolume.h hash.h main.cpp NetlinkManager.h ResponseCode.h VoldCommand.h VolumeManager.h

Asec.h Devmapper.cpp Fat.cpp logwrapper.c NetlinkHandler.cpp Process.cpp Volume.cpp Xwarp.cpp

CleanSpec.mk Devmapper.h Fat.h Loop.cpp NetlinkHandler.h Process.h vdc.c Volume.h Xwarp.h

CommandListener.cpp DirectVolume.cpp .git/ Loop.h NetlinkManager.cpp ResponseCode.cpp VoldCommand.cpp VolumeManager.cpp


Vold的原理与机制:

1、外部存储插入的时候,LinuxKernel会发出uevent事件给Vold

2Vold守护进程通过Socket机制从LinuxKernel获取相应的uevent,并解析成不同的状态;

3、然后在由MountService来获取这些由Vold解析出的相应状态决定发出什么样的广播、给Vold作出什么样的反应。

4、进而Vold依据MountService的反应稍加处理交由Kernel处理。

这里需要走出一个误区:当插入SD卡的时候Kernel发出ueventVold处理eventMountServiceVold获取相应信息发出广播,app在接收到广播之后会作出相应的处理;其实到这里SD卡并没有真正的被挂载到系统中,仅仅是触发了相应的uevent,而真正的挂载并没有执行。实际情况是如图1-1Vold架构所示,先得到Uevent在交由Vold进行解析,然后由MountService获取信息发出mountunmount等命令给Vold,在由Kernel进行针对存储设备的挂载、卸载、格式化等操作。

Vold不仅仅要处理来自KernelUevent等信息,还得处理来自MountService的信息。那么到底Vold是如何获取到Kernel发上来的Uevent信息?Vold又是如何从MountService获取到上层要发给Kernel的命令的呢?

在这里拥有一个重要的基类SocketListener。不仅对kernel发出的uevent进行监听还对MountServicekernel发出的命令进行监听。其常用类之间的结构关系如图1-2Vold重要类关系图



下图更加清晰的说明了Android针对StorageManager的处理流程。就更加凸显了SocketListener这个类的重要性;并且VoldMountService之间在进行进程间通信的时候并没有用到复杂Binder,而是直接的使用了Socket;这样就是的本身简单的Vold系统更加易懂。



二、VOLD进程的启动

vold是一个可执行文件。它的启动是在init.rc中的。

service vold/system/bin/vold

socketvold stream 0660 root mount

iopriobe 2

在这里把vold作为一个service启动。然后在创建一个socket用于oldmountservice通信。Ioprio是设置io调度优先级的。

首先看system/vold/main.cpp中的main函数。

1、创建节点/dev/block/vold

2VolumeManager*vm = VolumeManager::Instance();实例化,主要和mountservice通信




3NetlinkManager*nm = NetlinkManager::Instance();实例化,主要和kernel通信



4cl= new CommandListener();

主要是用来接受命令的。它是继承FrameworkListener,而FrameworkListener又继承SocketListenersocket的通信正是又它建立的。其中FrameworkListener用于接受命令并分发给各个*cmd





这里以VolumeCmd为例:可以看到其实就是把对应的对象添加到FrameworkListener






5 vm->setBroadcaster((SocketListener*) cl);

nm->setBroadcaster((SocketListener*) cl);

把上面new出来的CommandListener()放到VolumeManagerNetlinkManager中去。

6vm->start(),这里面是启动VolumeManager的,但是这个函数目前直接return0

7process_config(vm)这个函数主要是解析文件/etc/vold.fstab。这里面会有需要mount的信息。

一条典型的例子如下:

dev_mountsdcard /storage/sdcard0 auto/devices/platform/sprd-sdhci.0/mmc_host/mmc1

dev_mount代表挂载格式

sdcard代表挂载的标签

/mnt/sdcard0代表挂载点

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

后面目录为设备路径

process_config中会根据这些信息dv= new DirectVolume(vm, label, mount_point, -1);

最后通过vm->addVolume(dv);添加到VolumeManager中的变量mVolumes中去。

8nm->start()就是调用了NetlinkManager::start



在这个函数中主要做了3件事。

首先:创建一个socket

其次:socket建立连接

最后:把这个socket对象作为参数,创建一个NetlinkHandler。而这个NetlinkHandler是继承自NetlinkListener,而NetlinkListener又继承自SocketListener。再通过NetlinkHandlerstart方法调用SocketListener中的startListener()方法用来启动对socket端口的监听。

9coldboot("/sys/block");就是用来创建设备节点的。

10cl->startListener()通过调用CommandListener的父类SocketListenerstartListener方法启动对socket的监听。

11while(1)接下里VOLD就会一直在循环了,作为一个monitoring线程。

三、VOLD是如何接受LinuxkernelUEVENT事件的。

system/vold/NetlinkHandler.cpp中调用onEvent(NetlinkEvent*evt)方法来对UEVENT事件进行处理。其中NetlinkEvent这个参数是从system/core/libsysutils/src/NetlinkListener.cpp中的onDataAvailable(SocketClient*cli)函数中获得的。

onEvent函数中会根据NetlinkEvent的中的mSubsystem字符串的类型来做不同的处理.


针对不同的情况调用VolumeManager的不同方法去处理。

处理最后如果需要通知MountService,则最后还是会通过SocketListenersendBroadcast方法写入到socket中去。

四、VOLD是如何接受MountService的消息的

system/core/libsysutils/src/FrameworkListener.cpp中通过onDataAvailable读取socket的数据。并通过dispatchCommand将数据通过调用各个不同的VoldCommandrunCommand来执行。在其中通过argv[0]和各个VoldCommandname做匹配,以保证调用正确的VoldCommand。例如VolumeCommand

runCommand中会根据命令VolumeManager去处理。




CommandListener检测到framework 层的命令,调用VolumeManager的函数,

VolumeManager遍历Volume 清单找出对应的volume,调用volume 的函数。而volume类中的相关调用,最终调用到Linux 函数,完成相关操作。