1.Vold (Volume Daemon)介绍
vold进程接收来自内核的外部设备消息,用于管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等;当外部设备发生变化时,内核通过Netlink发送uEvent格式的消息给用户空间程序,Netlink 是一种基于异步通信机制,在内核与用户应用间进行双向数据传输的特殊 socket,用户态应用使用标准的socket API 就可以使用 netlink 提供的强大功能;
2.Vold 框架设计
Vold是native程序,用于管理和控制Android平台外部存储设备的管控中心,是一个后台运行的进程。它与Java层的MountService交互,Vold接收来自kernel的uevent消息,然后向上层转发,MountService接收来自vold的消息,同时也可以向vold发送控制命令。从以上Vold设计框架图中可以看到,Vold有三个模块,分别为NetlinkManager,VolumeManager,CommandListener。
NetlinkManager模块专门接收来自Linux内核uevent消息,并将消息转发给VolumeManager处理,VolumeManager模块接着又把相关信息通过CommandListener发送给MountService,MountService根据收到的消息会发送相应的处理命令给VolumeManager,VolumeManager接收到命令后直接对外部存储设备进行操作。
CommandListener模块内部封装良一个Socket用于跨进程通信,Java层的客户端MountService就是通过该Socket和服务端Vold进行通信的。
1.Netlink介绍
Netlink是Linux系统中用户空间进程和Kernel进行通信的一种机制,用户空间进程可以接收来自Kernel的消息,同时也可以向Kernel发送一些控制命令。
LINUX netlink机制一文中详细介绍了Netlink的用法。
2.Uevent介绍
uevent和Linux的设备文件系统及设备模型有关,是sysfs向用户空间发送的消息。消息格式实际上是一串字符串。当外部设备发生变化时,会引起Kernel发送Uevent消息;一般设备在/sys对应的目录下有个叫uevent的文件,往该文件里写入指定数据,也会触发Kernel发送和该设备相关的uevent消息,内核通过uevent告知外部存储系统发生的变化。
3.Vold 源码分析
\system\vold\main.cpp
- int main()
- {
- VolumeManager *vm;
- CommandListener *cl;
- NetlinkManager *nm;
-
- mkdir("/dev/block/vold", 0755);
-
-
- vm = VolumeManager::Instance();
- nm = NetlinkManager::Instance();
-
-
- cl = new CommandListener();
- vm->setBroadcaster((SocketListener *) cl);
- nm->setBroadcaster((SocketListener *) cl);
-
-
- vm->start();
-
-
- process_config(vm);
-
-
- nm->start();
-
-
-
- coldboot("/sys/block");
-
-
- cl->startListener();
-
-
- while(1) {
- sleep(1000);
- }
-
- exit(0);
- }
/etc/vold.fstab的内容如下:
- <span style="font-family:Verdana, Arial, Helvetica, sans-serif;font-size:18px;"><span style="line-height: 24px; background-color: rgb(254, 254, 242);">#######################
- ## Regular device mount
- ##
- ## Format: dev_mount <label> <mount_point> <part> <sysfs_path1...>
- ## label - Label for the volume
- ## mount_point - Where the volume will be mounted
- ## part - Partition # (1 based), or 'auto' for first usable partition.
- ## <sysfs_path> - List of sysfs paths to source devices
- ######################
-
- # Mounts the first usable partition of the specified device
- #dev_mount sdcard /mnt/sdcard auto /block/mmcblk0
- dev_mount internal /mnt/sdcard 19 /devices/platform/sprd-sdhci.3/mmc_host/mmc3
- dev_mount sdcard /mnt/sdcard/external auto /devices/platform/sprd-sdhci.0/mmc_host/mmc0</span></span>
process_config解析vold.fstab文件:
- static int process_config(VolumeManager *vm) {
-
- fp = fopen("/etc/vold.fstab", "r")
-
- while(fgets(line, sizeof(line), fp)) {
- const char *delim = " \t";
- char *type, *label, *mount_point, *part, *mount_flags, *sysfs_path;
-
- type = strtok_r(line, delim, &save_ptr)
- label = strtok_r(NULL, delim, &save_ptr)
- mount_point = strtok_r(NULL, delim, &save_ptr)
-
- part = strtok_r(NULL, delim, &save_ptr)
- if (!strcmp(part, "auto")) {
-
- dv = new DirectVolume(vm, label, mount_point, -1);
- } else {
- dv = new DirectVolume(vm, label, mount_point, atoi(part));
- }
-
- while ((sysfs_path = strtok_r(NULL, delim, &save_ptr))) {
- dv->addPath(sysfs_path)
- }
-
- vm->addVolume(dv);
- }
-
- fclose(fp);
- return 0;
- }
4.Vold各模块分析
前面介绍了Vold包含NetlinkManager,VolumeManager,CommandListener三大模块,他们之间的关系如下:
接下来就分别针对每个模块进行详细分析。
1.NetlinkManager模块
NetlinkManager模块接收从Kernel发送的Uevent消息,解析转换成NetlinkEvent对象;再将此NetlinkEvent对象传递给VolumeManager处理。
启动流程
1)构造NetlinkManager实例:nm = NetlinkManager::Instance()
2)设置事件广播监听:nm->setBroadcaster((SocketListener *) cl)
3)启动NetlinkManager:nm->start()
构造NetlinkManager实例
- NetlinkManager *NetlinkManager::Instance() {
- if (!sInstance)
- sInstance = new NetlinkManager();
- return sInstance;
- }
启动NetlinkManager
- int NetlinkManager::start() {
-
- struct sockaddr_nl nladdr;
-
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = getpid();
- nladdr.nl_groups = 0xffffffff;
-
- mSock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);
-
- setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz);
- setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on);
-
- bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr);
-
-
- mHandler = new NetlinkHandler(mSock);
- mHandler->start();
- return 0;
- }
在启动NetlinkManager时,初始化socket用于创建NetlinkManager的属性变量mHandle实例,并启动NetlinkHandler,NetlinkHandler继承于NetlinkListener,NetlinkListener又继承于SocketListener,因此在构造NetlinkHandler实例时首先构造SocketListener及NetlinkListener,构造NetlinkListener对象的父类对象SocketListener:
- SocketListener::SocketListener(int socketFd, bool listen) {
- init(NULL, socketFd, listen, false);
- }
- void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
- mListen = listen;
- mSocketName = socketName;
- mSock = socketFd;
- mUseCmdNum = useCmdNum;
- pthread_mutex_init(&mClientsLock, NULL);
- mClients = new SocketClientCollection();
- }
NetlinkListener构造函数:
- NetlinkListener::NetlinkListener(int socket) :
- SocketListener(socket, false) {
- mFormat = NETLINK_FORMAT_ASCII;
- }
NetlinkHandler构造函数:
- NetlinkHandler::NetlinkHandler(int listenerSocket) :
- NetlinkListener(listenerSocket) {
- }
因此构造NetlinkHandler实例过程仅仅创建良一个socket客户端连接。
NetlinkHandler start:
- int NetlinkHandler::start() {
-
- return this->startListener();
- }
SocketListener start:
- int SocketListener::startListener() {
-
- if (mListen && listen(mSock, 4) < 0) {
- return -1;
- } else if (!mListen){
-
-
- mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
- }
-
-
- pipe(mCtrlPipe);
-
- pthread_create(&mThread, NULL, SocketListener::threadStart, this);
- }

uevent消息监听线程
启动NetlinkHandler过程通过创建一个SocketListener工作线程来
监听Kernel netlink发送的UEvent消息,该线程完成的工作:
- void *SocketListener::threadStart(void *obj) {
-
-
- SocketListener *me = reinterpret_cast<SocketListener *>(obj);
-
- me->runListener();
-
- pthread_exit(NULL);
-
- return NULL;
-
- }
SocketListener 线程消息循环:
- void SocketListener::runListener() {
-
- SocketClientCollection *pendingList = new SocketClientCollection();
-
- while(1) {
- fd_set read_fds;
-
- if (mListen) {
- max = mSock;
- FD_SET(mSock, &read_fds);
- }
-
- FD_SET(mCtrlPipe[0], &read_fds);
- pthread_mutex_lock(&mClientsLock);
- for (it = mClients->begin(); it != mClients->end(); ++it) {
- int fd = (*it)->getSocket();
- FD_SET(fd, &read_fds);
- if (fd > max)
- max = fd;
- }
- pthread_mutex_unlock(&mClientsLock);
-
-
- rc = select(max + 1, &read_fds, NULL, NULL, NULL);
-
- if (FD_ISSET(mCtrlPipe[0], &read_fds))
- break;
-
- if (mListen && FD_ISSET(mSock, &read_fds)) {
-
- struct sockaddr addr;
- do {
-
- c = accept(mSock, &addr, &alen);
- } while (c < 0 && errno == EINTR);
-
-
- pthread_mutex_lock(&mClientsLock);
- mClients->push_back(new SocketClient(c, true, mUseCmdNum));
- pthread_mutex_unlock(&mClientsLock);
- }
-
-
- pendingList->clear();
-
- pthread_mutex_lock(&mClientsLock);
- for (it = mClients->begin(); it != mClients->end(); ++it) {
- int fd = (*it)->getSocket();
- if (FD_ISSET(fd, &read_fds)) {
- pendingList->push_back(*it);
- }
- }
- pthread_mutex_unlock(&mClientsLock);
-
-
- while (!pendingList->empty()) {
- it = pendingList->begin();
- SocketClient* c = *it;
- pendingList->erase(it);
-
- if (!onDataAvailable(c) && mListen) {
-
- }
- }
- }
- }
在消息循环中调用onDataAvailable处理消息,onDataAvailable是个虚函数,NetlinkListener重写了此函数。
- bool NetlinkListener::onDataAvailable(SocketClient *cli)
- {
-
- int socket = cli->getSocket();
-
- count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv(
- socket, mBuffer, sizeof(mBuffer), &uid));
-
- NetlinkEvent *evt = new NetlinkEvent();
- evt->decode(mBuffer, count, mFormat);
-
-
- onEvent(evt);
- }
将接收的Uevent数据转化成NetlinkEvent数据,调用onEvent处理,NetlinkListener子类NetlinkHandler重写了此函数。
- void NetlinkHandler::onEvent(NetlinkEvent *evt) {
-
-
- VolumeManager *vm = VolumeManager::Instance();
-
-
- const char *subsys = evt->getSubsystem();
-
-
- if (!strcmp(subsys, "block")) {
- vm->handleBlockEvent(evt);
-
- }
- }
NetlinkManager通过NetlinkHandler将接收到Kernel内核发送的Uenvet消息,转化成了NetlinkEvent结构数据传递给VolumeManager处理,uevent消息的上传流程:

2.VolumeManager模块
启动流程
1)构造VolumeManager对象实例
2)设置事件广播监听
3)启动VolumeManager
4)配置VolumeManager
VolumeManager类关系图:

DirectVolume是一个实体存储设备的抽象,通过系统调用直接操作存储设备。VolumeManager的SocketListenner与NetlinkManager的SocketListenner有所不同的:
NetlinkManager构造的SocketListenner:Kernel与Vold通信;
VolumeManager构造的SocketListenner:Native Vold与Framework MountService 通信;
NetlinkManager与VolumeManager交互流程图:

1.构造VolumeManager对象
- VolumeManager *VolumeManager::Instance() {
- if (!sInstance)
- sInstance = new VolumeManager();
- return sInstance;
- }
-
- VolumeManager::VolumeManager() {
- mDebug = false;
- mVolumes = new VolumeCollection();
- mActiveContainers = new AsecIdCollection();
- mBroadcaster = NULL;
- mUmsSharingCount = 0;
- mSavedDirtyRatio = -1;
-
- mUmsDirtyRatio = 20;
- mVolManagerDisabled = 0;
- }
2.启动VolumeManager
- int VolumeManager::start() {
- return 0;
- }
VolumeManager启动过程什么都没有做。
3.uevent事件处理
前面NetlinkManager模块中介绍到,NetlinkHandler在onEvent函数中,将NetlinkEvent事件转交给VolumeManager处理:
- void NetlinkHandler::onEvent(NetlinkEvent *evt) {
- ……
-
- if (!strcmp(subsys, "block")) {
- vm->handleBlockEvent(evt);
- }
- }
- void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
-
- const char *devpath = evt->findParam("DEVPATH");
-
-
- for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
- if (!(*it)->handleBlockEvent(evt)) {
- hit = true;
- break;
- }
- }
VolumeManager将消息交给各个DirectVolume对象处理:
- int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
-
- const char *dp = evt->findParam("DEVPATH");
-
- PathCollection::iterator it;
-
- for (it = mPaths->begin(); it != mPaths->end(); ++it) {
-
- if (!strncmp(dp, *it, strlen(*it))) {
-
- int action = evt->getAction();
-
- const char *devtype = evt->findParam("DEVTYPE");
- SLOGE("DirectVolume::handleBlockEvent() evt's DEVPATH= %s DEVTYPE= %s action= %d",dp, devtype, action);
- if (action == NetlinkEvent::NlActionAdd) {
- int major = atoi(evt->findParam("MAJOR"));
- int minor = atoi(evt->findParam("MINOR"));
- char nodepath[255];
-
- snprintf(nodepath,sizeof(nodepath), "/dev/block/vold/%d:%d",major, minor);
- SLOGE("DirectVolume::handleBlockEvent() NlActionAdd - /dev/block/vold/%d:%d\n", major, minor);
- if (createDeviceNode(nodepath, major, minor)) {
- SLOGE("Error making device node '%s' (%s)", nodepath,strerror(errno));
- }
-
- if (!strcmp(devtype, "disk")) {
- handleDiskAdded(dp, evt);
-
- } else {
- handlePartitionAdded(dp, evt);
- }
-
- } else if (action == NetlinkEvent::NlActionRemove) {
- SLOGE("Volume partition %d:%d removed", atoi(evt->findParam("MAJOR")), atoi(evt->findParam("MINOR")));
-
- if (!strcmp(devtype, "disk")) {
- handleDiskRemoved(dp, evt);
-
- } else {
- handlePartitionRemoved(dp, evt);
- }
-
- } else if (action == NetlinkEvent::NlActionChange) {
-
- if (!strcmp(devtype, "disk")) {
- handleDiskChanged(dp, evt);
-
- } else {
- handlePartitionChanged(dp, evt);
- }
- } else {
- SLOGW("Ignoring non add/remove/change event");
- }
-
- return 0;
- }
- }
- errno = ENODEV;
- return -1;
- }
每一个Volume可能对应多个Path;即一个挂载点对应多个物理设备,因此VolumeManager中的每一个Volume对象都需要处理SD状态变换消息,当新增一个disk时:
- void DirectVolume::handleDiskAdded(const char *devpath, NetlinkEvent *evt) {
-
- mDiskMajor = atoi(evt->findParam("MAJOR"));
- mDiskMinor = atoi(evt->findParam("MINOR"));
-
-
- const char *tmp = evt->findParam("NPARTS");
- mDiskNumParts = atoi(tmp);
-
- if (mDiskNumParts == 0) {
-
- setState(Volume::State_Idle);
- } else {
-
- setState(Volume::State_Pending);
- }
-
- char msg[255];
- snprintf(msg, sizeof(msg), "Volume %s %s disk inserted (%d:%d)",getLabel(), getMountpoint(), mDiskMajor, mDiskMinor);
-
- mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg, false);
- }
将新增一个disk以消息的方式通过CommandListener向MountService发送,由于CommandListener继承于FrameworkListener,而FrameworkListener又继承于SocketListener,CommandListener和FrameworkListener都没用重写父类的sendBroadcast方法,因此消息是通过
SocketListener的sendBroadcast函数向上层发送的,VolumeManager通知上层的消息流程图:
- void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno)
- {
- pthread_mutex_lock(&mClientsLock);
-
-
- for (i = mClients->begin(); i != mClients->end(); ++i) {
- (*i)->sendMsg(code, msg, addErrno, false);
- }
- pthread_mutex_unlock(&mClientsLock);
- }
3.CommandListener模块
1)构造CommandListener对象实例
2)调用startListener函数启动监听
1.构造CommandListener对象
- CommandListener::CommandListener() :
- FrameworkListener("vold", true) {
-
-
-
- registerCmd(new DumpCmd());
-
- registerCmd(new VolumeCmd());
-
- registerCmd(new AsecCmd());
-
- registerCmd(new ObbCmd());
-
- registerCmd(new StorageCmd());
-
- registerCmd(new XwarpCmd());
-
- registerCmd(new CryptfsCmd());
-
- }
父类FrameworkListener构造:
- FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :
- SocketListener(socketName, true, withSeq) {
- init(socketName, withSeq);
- }
直接调用init函数;
- void FrameworkListener::init(const char *socketName, bool withSeq) {
- mCommands = new FrameworkCommandCollection();
- errorRate = 0;
- mCommandCount = 0;
- mWithSeq = withSeq;
- }
SocketListener的构造函数:
- SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {
- init(socketName, -1, listen, useCmdNum);
- }
同样调用init函数进行初始化:
- void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
- mListen = listen;
- mSocketName = socketName;
- mSock = socketFd;
- mUseCmdNum = useCmdNum;
- pthread_mutex_init(&mClientsLock, NULL);
- mClients = new SocketClientCollection();
- }
构造CommandListener对象过程中,首先注册了各种命令,并创建良一个socket客户端连接。命令注册过程:
- void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
- mCommands->push_back(cmd);
- }
将各种命令存放到mCommand列表中。
2.启动CommandListener监听
- int SocketListener::startListener() {
-
- mSock = android_get_control_socket(mSocketName);
-
-
- if (mListen && < 0) {
- return -1;
- } else if (!mListen){
- mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
- }
-
-
- pipe(mCtrlPipe);
-
- pthread_create(&mThread, NULL, SocketListener::threadStart, this);
- }
-
- void *SocketListener::threadStart(void *obj) {
- SocketListener *me = reinterpret_cast<SocketListener *>(obj);
- me->runListener();
- }
-
- void SocketListener::runListener() {
-
- SocketClientCollection *pendingList = new SocketClientCollection();
-
- while(1) {
- fd_set read_fds;
-
- if (mListen) {
- max = mSock;
- FD_SET(mSock, &read_fds);
- }
-
- FD_SET(mCtrlPipe[0], &read_fds);
- pthread_mutex_lock(&mClientsLock);
- for (it = mClients->begin(); it != mClients->end(); ++it) {
- int fd = (*it)->getSocket();
- FD_SET(fd, &read_fds);
- if (fd > max)
- max = fd;
- }
- pthread_mutex_unlock(&mClientsLock);
-
-
- rc = select(max + 1, &read_fds, NULL, NULL, NULL);
-
- if (FD_ISSET(mCtrlPipe[0], &read_fds))
- break;
-
-
- if (mListen && FD_ISSET(mSock, &read_fds)) {
-
- struct sockaddr addr;
- do {
- c = accept(mSock, &addr, &alen);
- } while (c < 0 && errno == EINTR);
-
-
- pthread_mutex_lock(&mClientsLock);
- mClients->push_back(new SocketClient(c, true, mUseCmdNum));
- pthread_mutex_unlock(&mClientsLock);
- }
-
-
- pendingList->clear();
-
- pthread_mutex_lock(&mClientsLock);
- for (it = mClients->begin(); it != mClients->end(); ++it) {
- int fd = (*it)->getSocket();
- if (FD_ISSET(fd, &read_fds)) {
- pendingList->push_back(*it);
- }
- }
- pthread_mutex_unlock(&mClientsLock);
-
-
- while (!pendingList->empty()) {
- it = pendingList->begin();
- SocketClient* c = *it;
-
- if (!onDataAvailable(c) && mListen) {
-
- ……
- }
- }
- }
- }
启动CommandListener监听过程其实就是创建一个监听的工作线程,用于监听客户端即MountService发过来的命令。
3.消息处理
当接收到MountService发送的消息时,将回调onDataAvailable函数进行处理。CommandListener父类FrameworkCommand重写了消息处理onDataAvailable函数。
- bool FrameworkListener::onDataAvailable(SocketClient *c) {
- char buffer[255];
-
- len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer)));
- for (i = 0; i < len; i++) {
- if (buffer[i] == '\0') {
-
- dispatchCommand(c, buffer + offset);
- offset = i + 1;
- }
- }
- return true;
- }
-
- void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
- char *argv[FrameworkListener::CMD_ARGS_MAX];
-
- ……
-
-
- for (i = mCommands->begin(); i != mCommands->end(); ++i) {
- FrameworkCommand *c = *i;
-
- if (!strcmp(argv[0], c->getCommand())) {
-
- c->runCommand(cli, argc, argv);
- goto out;
- }
- }
- out:
- return;
- }

对于
VolumeCommand,其runCommand函数为:
- int CommandListener::VolumeCmd::runCommand(SocketClient *cli,int argc, char **argv) {
- dumpArgs(argc, argv, -1);
- if (argc < 2) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
- return 0;
- }
- VolumeManager *vm = VolumeManager::Instance();
- int rc = 0;
-
- if (!strcmp(argv[1], "list")) {
- return vm->listVolumes(cli);
- } else if (!strcmp(argv[1], "debug")) {
- if (argc != 3 || (argc == 3 && (strcmp(argv[2], "off") && strcmp(argv[2], "on")))) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume debug <off/on>", false);
- return 0;
- }
- vm->setDebug(!strcmp(argv[2], "on") ? true : false);
-
- } else if (!strcmp(argv[1], "mount")) {
- if (argc != 3) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount <path>", false);
- return 0;
- }
- rc = vm->mountVolume(argv[2]);
-
- } else if (!strcmp(argv[1], "unmount")) {
- if (argc < 3 || argc > 4 ||
- ((argc == 4 && strcmp(argv[3], "force")) &&
- (argc == 4 && strcmp(argv[3], "force_and_revert")))) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force|force_and_revert]", false);
- return 0;
- }
-
- bool force = false;
- bool revert = false;
- if (argc >= 4 && !strcmp(argv[3], "force")) {
- force = true;
- } else if (argc >= 4 && !strcmp(argv[3], "force_and_revert")) {
- force = true;
- revert = true;
- }
- rc = vm->unmountVolume(argv[2], force, revert);
-
- } else if (!strcmp(argv[1], "format")) {
- if (argc != 3) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path>", false);
- return 0;
- }
- rc = vm->formatVolume(argv[2]);
-
- } else if (!strcmp(argv[1], "share")) {
- if (argc != 4) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: volume share <path> <method>", false);
- return 0;
- }
- rc = vm->shareVolume(argv[2], argv[3]);
- } else if (!strcmp(argv[1], "unshare")) {
- if (argc != 4) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: volume unshare <path> <method>", false);
- return 0;
- }
- rc = vm->unshareVolume(argv[2], argv[3]);
- } else if (!strcmp(argv[1], "shared")) {
- bool enabled = false;
- if (argc != 4) {
- cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: volume shared <path> <method>", false);
- return 0;
- }
-
- if (vm->shareEnabled(argv[2], argv[3], &enabled)) {
- cli->sendMsg(
- ResponseCode::OperationFailed, "Failed to determine share enable state", true);
- } else {
- cli->sendMsg(ResponseCode::ShareEnabledResult,
- (enabled ? "Share enabled" : "Share disabled"), false);
- }
- return 0;
- } else {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
- }
-
- if (!rc) {
- cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
- } else {
- int erno = errno;
- rc = ResponseCode::convertFromErrno();
- cli->sendMsg(rc, "volume operation failed", true);
- }
- return 0;
- }
针对不同的命令,调用VolumeManager的不同函数对存储设备进行操作,如挂载磁盘命令,则调用mountVolume函数:
- int VolumeManager::mountVolume(const char *label) {
-
- Volume *v = lookupVolume(label);
- if (!v) {
- errno = ENOENT;
- return -1;
- }
- return v->mountVol();
- }
调用Volume的mountVol函数来挂载设备。MountServcie发送命令的流程图:

整个Vold处理过程框架图如下:
