Vold学习笔记

本文主要参考学习了老邓的Vold章节。

平台:android4.0
场景:客户要求系统默认对NTFS的SD卡支持识别。
时间:2012.7.28

Android系统默认支持FAT文件系统,不支持NTFS,EXFAT。其原因不在于技术方面,而是版权。
在全志的平台上,以上文件系统都是支持的。所以在做分析时,也参考了全志平台的做法。

vold是Volume Daemon的简称,其是用于管理和控制android平台外部存储设备的后台进程,相关代码在system/vold下面。
1.vold使用socket的进行跨进程通信。其中重要的几个文件分别为:NetlinkManager.cpp,
VolumeManager.cpp,
CommandListener.cpp,
Volume.cpp。
在框架中,其对应的是MountService,此为框架中存储设备挂载的核心类。其通过socket与CL通信,为Client端,其监听CL传上来的kernel消息(设备挂载,移除等),并向CL发送命令,从而控制vold进行mount,unmount等操作。

2.关于Uevent。它实际上就是一串字符串。
在vold中,kernel上报的uevent中封装了DEVPATH信息等,DEVPATH信息在后面被用来比对对应的挂载设备,从而区分设备,进行操作。
设备一般在/sys对应的目录下存在一个event文件。当往文件中写入指定的数据,也会触发kernel发送和该设备相关的Uevent消息。
Vold启动时,就使用这种方式,进而触发kernel发送Uevent消息,使得vold能够得到相关的设备信息。

3.NetlinkHandler继承与SocketListener。其中的onDataAvailable()函数,在收到数据时被调用。NetlinkHandler被多线程使用,其根据kernel上报的Uevent进行相应的处理。
if (!strcmp(subsys, “block”)) {
vm->handleBlockEvent(evt);
} else if (!strcmp(subsys, “switch”)) {
vm->handleSwitchEvent(evt);
} else if (!strcmp(subsys, “battery”)) {
} else if (!strcmp(subsys, “power_supply”)) {
}
此处,便于VolumeManager有了联系。

4.VolumeManager即为挂载设备管理者。每一个挂载上来的设备,对应一个volume对象。
在vold的main()函数中,有一个调用process_config(vm),其为解析system/etc/vold.fstab文件,每一个dev_mount解析出来,构造一个DirectVolume对象,其继承与Volume。
在process_config()中,会调用dv->addPath()方法,将DV对象和其DEVPATH进行绑定,即为后面的对比调用做好了准备。其最后会调用vm->addVolume(dv),将vold.fstab中申明的dev_mount都加入到VM的mVolumes变量中,以供后面的handleBlockEvent()的调用。

5.CommandListener继承于SocketListener,其为socket的service端。接收Client(即mountservice)发送来的命令,调用相应的runCommand()进行处理。

6.当一个SD卡设备插入时:
(1).NetlinkHandler收到kernel上报的Uevent,并调用vm->handleBlockEvent(evt);
(2).Vm::handleBlockEvent()中,
会遍历通过process_config()扩充的变量mVolumes,进行每个对象的DV::handleBlockEvent()方法的调用;
(3).DV::handleBlockEvent()===>DV::handleDiskAdded(),通过VM中的CL对象进行socket通信,通知mountservice;
(4).mountservice::onEvent()===>doMountVolume()===>mConnector.doCommand(String.format(“volume mount %s”, path));
(5).CommandListener::VolumeCmd::runCommand===>vm->mountVolume(argv[2])===>通过挂载路径比对出对应的volume对象===>v->mountVol();
(6).Volume中,Fat::check()===>Fat::doMount(),从而调用到Fat.cpp中的domount()函数进行挂载,最后通过setState()方法,将结果通过CL返回给mountservice,mountservice随即发出ACTION_MEDIA_MOUNTED广播。

解决方法:
(1).修改Volume .cpp。在mountVol()中
ret = Fat::doMount(devicePath, getMountpoint(), false, false, 1000, 1015, 0002, true);
if ((ret != 0) && (ret != EROFS)) {
SLOGE(“%s failed to mount via VFAT (%s)\n”, devicePath, strerror(errno));
//add by fox 2012.7.28
if(Ntfs::doMount(devicePath, getMountpoint(), false, 1000)){
SLOGE(“%s failed to mount via NTFS (%s)\n”, devicePath, strerror(errno));
setState(Volume::State_Idle);
return -1;
}
//end
(2).添加Ntfs.cpp和Ntfs.h文件。其中关键的部分是,挂载NTFS使用的是第三方的可执行文件,此文件需要添加到system/bin目录下。
static char NTFS_3G_PATH[] = “/system/bin/ntfs-3g”。ntfs-3g即为挂载使用的可执行文件。

你可能感兴趣的:(Vold学习笔记)