1.Vold (Volume Daemon)介绍
vold进程接收来自内核的外部设备消息,用于管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等;当外部设备发生变化时,内核通过Netlink发送uEvent格式的消息给用户空间程序,Netlink 是一种基于异步通信机制,在内核与用户应用间进行双向数据传输的特殊 socket,用户态应用使用标准的socket API 就可以使用 netlink 提供的强大功能;
2.Vold 框架设计
![](https://i-blog.csdnimg.cn/blog_migrate/3f0fa3225cc3c54a21dd03677b9136ef.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0cb8d27771055ab2db224976034a69f6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/858bf76914ae8feb3ea2bd231de6c84c.png)
1.Netlink介绍
2.Uevent介绍
3.Vold 源码分析
int main()
{
VolumeManager *vm;
CommandListener *cl;
NetlinkManager *nm;
//创建vold设备文件夹
mkdir("/dev/block/vold", 0755);
//初始化Vold相关的类实例 single
vm = VolumeManager::Instance();
nm = NetlinkManager::Instance();
//CommandListener 创建vold socket监听上层消息
cl = new CommandListener();
vm->setBroadcaster((SocketListener *) cl);
nm->setBroadcaster((SocketListener *) cl);
//启动VolumeManager
vm->start();
//根据配置文件/etc/vold.fstab 初始化VolumeManager
process_config(vm);
//启动NetlinkManager socket监听内核发送uevent
nm->start();
//向/sys/block/目录下所有设备uevent文件写入“add\n”,
//触发内核sysfs发送uevent消息
coldboot("/sys/block");
//启动CommandListener监听vold socket
cl->startListener();
// Eventually we'll become the monitoring thread
while(1) {
sleep(1000);
}
exit(0);
}
/etc/vold.fstab的内容如下:
<span style="background-color:#fefef2">#######################
## 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>
process_config解析vold.fstab文件:
static int process_config(VolumeManager *vm) {
//打开vold.fstab的配置文件
fp = fopen("/etc/vold.fstab", "r")
//解析vold.fstab 配置存储设备的挂载点
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)
//判断分区 auto没有分区
part = strtok_r(NULL, delim, &save_ptr)
if (!strcmp(part, "auto")) {
//创建DirectVolume对象 相关的挂载点设备的操作
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)
}
//将DirectVolume 添加到VolumeManager管理
vm->addVolume(dv);
}
fclose(fp);
return 0;
}
4.Vold各模块分析
![](https://i-blog.csdnimg.cn/blog_migrate/04ca9369fd831f59da5ab6bcf7b527e1.png)
1.NetlinkManager模块
1)构造NetlinkManager实例:nm = NetlinkManager::Instance()
2)设置事件广播监听:nm->setBroadcaster((SocketListener *) cl)
3)启动NetlinkManager:nm->start()
![](https://i-blog.csdnimg.cn/blog_migrate/efc2d89a0e4a7ed2d4a846d469997969.png)
构造NetlinkManager实例
NetlinkManager *NetlinkManager::Instance() {
if (!sInstance) //采用单例模式创建NetlinkManager实例
sInstance = new NetlinkManager();
return sInstance;
}
启动NetlinkManager
int NetlinkManager::start() {
//netlink使用的socket结构
struct sockaddr_nl nladdr;
//初始化socket数据结构
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff;
//创建socket PF_NETLINK类型
mSock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);
//配置socket 大小
setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz);
setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on);
//bindsocket地址
bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr);
//创建NetlinkHandler 传递socket标识,并启动
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客户端连接。
int NetlinkHandler::start() {
//父类startListener
return this->startListener();
}
SocketListener start:
int SocketListener::startListener() {
//NetlinkHandler mListen为false
if (mListen && listen(mSock, 4) < 0) {
return -1;
} else if (!mListen){
//mListen为false 用于netlink消息监听
//创建SocketClient作为SocketListener 的客户端
mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
}
//创建匿名管道
pipe(mCtrlPipe);
//创建线程执行函数threadStart 参this
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() {
//SocketClient List
SocketClientCollection *pendingList = new SocketClientCollection();
while(1) {
fd_set read_fds;
//mListen 为false
if (mListen) {
max = mSock;
FD_SET(mSock, &read_fds);
}
//加入一组文件描述符集合 选择fd最大的max
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;
//mListen 为false
if (mListen && FD_ISSET(mSock, &read_fds)) {
//mListen 为ture 表示正常监听socket
struct sockaddr addr;
do {
//接收客户端连接
c = accept(mSock, &addr, &alen);
} while (c < 0 && errno == EINTR);
//此处创建一个客户端SocketClient加入mClients列表中,异步延迟处理
pthread_mutex_lock(&mClientsLock);
mClients->push_back(new SocketClient(c, true, mUseCmdNum));
pthread_mutex_unlock(&mClientsLock);
}
/* Add all active clients to the pending list first */
pendingList->clear();
//将所有有消息的Client加入到pendingList中
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);
//处理有数据发送的socket 虚函数
if (!onDataAvailable(c) && mListen) {
//mListen为false
}
}
}
}
在消息循环中调用onDataAvailable处理消息,onDataAvailable是个虚函数,NetlinkListener重写了此函数。
bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
//获取socket id
int socket = cli->getSocket();
//接收netlink uevent消息
count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv(
socket, mBuffer, sizeof(mBuffer), &uid));
//解析uevent消息为NetlinkEvent消息
NetlinkEvent *evt = new NetlinkEvent();
evt->decode(mBuffer, count, mFormat);
//处理NetlinkEvent onEvent虚函数
onEvent(evt);
}
将接收的Uevent数据转化成NetlinkEvent数据,调用onEvent处理,NetlinkListener子类NetlinkHandler重写了此函数。
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
//获取VolumeManager实例
VolumeManager *vm = VolumeManager::Instance();
//设备类型
const char *subsys = evt->getSubsystem();
//将消息传递给VolumeManager处理
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;
// set dirty ratio to 20 when UMS is active
mUmsDirtyRatio = 20;
mVolManagerDisabled = 0;
}
2.启动VolumeManager
int VolumeManager::start() {
return 0;
}
VolumeManager启动过程什么都没有做。
3.uevent事件处理
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
……
//将消息传递给VolumeManager处理
if (!strcmp(subsys, "block")) {
vm->handleBlockEvent(evt);
}
}
void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
//有状态变化设备路径
const char *devpath = evt->findParam("DEVPATH");
//遍历VolumeManager中所管理Volume对象(各存储设备代码抽象)
for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
if (!(*it)->handleBlockEvent(evt)) {
hit = true;
break;
}
}
VolumeManager将消息交给各个DirectVolume对象处理:
int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
//从NetlinkEvent消息中取出有状态变化设备路径
const char *dp = evt->findParam("DEVPATH");
PathCollection::iterator it;
//遍历所有的存储设备
for (it = mPaths->begin(); it != mPaths->end(); ++it) {
//根据存储设备路径进行匹配
if (!strncmp(dp, *it, strlen(*it))) {
/* 从NetlinkEvent消息中取出设备变化的动作 */
int action = evt->getAction();
/* 从NetlinkEvent消息中取出设备类型 */
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) {
//没有分区,Volume状态为Idle
setState(Volume::State_Idle);
} else {
//有分区未加载,设置Volume状态Pending
setState(Volume::State_Pending);
}
//格式化通知msg:"Volume sdcard /mnt/sdcard disk inserted (179:0)"
char msg[255];
snprintf(msg, sizeof(msg), "Volume %s %s disk inserted (%d:%d)",getLabel(), getMountpoint(), mDiskMajor, mDiskMinor);
//调用VolumeManager中的Broadcaster——>CommandListener 发送此msg
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg, false);
}
将新增一个disk以消息的方式通过CommandListener向MountService发送,由于CommandListener继承于FrameworkListener,而FrameworkListener又继承于SocketListener,CommandListener和FrameworkListener都没用重写父类的sendBroadcast方法,因此消息是通过
SocketListener的sendBroadcast函数向上层发送的,VolumeManager通知上层的消息流程图:
![](https://i-blog.csdnimg.cn/blog_migrate/1e02fa5f423aa5644b39b3af5db7f9ba.png)
void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno)
{
pthread_mutex_lock(&mClientsLock);
//遍历所有的消息接收时创建的Client SocketClient
// SocketClient将消息通过socket(“vold”)通信
for (i = mClients->begin(); i != mClients->end(); ++i) {
(*i)->sendMsg(code, msg, addErrno, false);
}
pthread_mutex_unlock(&mClientsLock);
}
3.CommandListener模块
2)调用startListener函数启动监听
![](https://i-blog.csdnimg.cn/blog_migrate/f8b565ce03ee6c0a3f78b0727811e26e.png)
1.构造CommandListener对象
CommandListener::CommandListener() :
FrameworkListener("vold", true) {
//注册Framework发送的相关命令 Command模式
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() {
//mSocketName = “Vold”
mSock = android_get_control_socket(mSocketName);
//NetlinkHandler mListen为true 监听socket
if (mListen && < 0) {
return -1;
} else if (!mListen){
mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
}
//创建匿名管道
pipe(mCtrlPipe);
//创建线程执行函数threadStart 参数this
pthread_create(&mThread, NULL, SocketListener::threadStart, this);
}
void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast<SocketListener *>(obj);
me->runListener();
}
void SocketListener::runListener() {
//SocketClient List
SocketClientCollection *pendingList = new SocketClientCollection();
while(1) {
fd_set read_fds;
//mListen 为true
if (mListen) {
max = mSock;
FD_SET(mSock, &read_fds);
}
//加入一组文件描述符集合 选择fd最大的max select有关
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;
//mListen 为true
if (mListen && FD_ISSET(mSock, &read_fds)) {
//mListen 为ture 表示正常监听socket
struct sockaddr addr;
do {
c = accept(mSock, &addr, &alen);
} while (c < 0 && errno == EINTR);
//创建一个客户端SocketClient,加入mClients列表中 到异步延迟处理
pthread_mutex_lock(&mClientsLock);
mClients->push_back(new SocketClient(c, true, mUseCmdNum));
pthread_mutex_unlock(&mClientsLock);
}
/* Add all active clients to the pending list first */
pendingList->clear();
//将所有有消息的Client加入到pendingList中
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);
/* Process the pending list, since it is owned by the thread,*/
while (!pendingList->empty()) {
it = pendingList->begin();
SocketClient* c = *it;
//处理有数据发送的socket
if (!onDataAvailable(c) && mListen) {
//mListen为true
……
}
}
}
}
启动CommandListener监听过程其实就是创建一个监听的工作线程,用于监听客户端即MountService发过来的命令。
3.消息处理
当接收到MountService发送的消息时,将回调onDataAvailable函数进行处理。CommandListener父类FrameworkCommand重写了消息处理onDataAvailable函数。
bool FrameworkListener::onDataAvailable(SocketClient *c) {
char buffer[255];
//读取socket消息
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;
}
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
Volume *v = lookupVolume(label);
if (!v) {
errno = ENOENT;
return -1;
}
return v->mountVol();
}
调用Volume的mountVol函数来挂载设备。MountServcie发送命令的流程图:
整个Vold处理过程框架图如下: