Android-vold源码分析之卸载SD卡

本文分析卸载sd卡的源码,这些涉及的内容比较少,走过就行。在Android系统,系统设置里面,
提供了挂载,卸载与格式化的功能。在这里,我们可以回忆一下,Android在挂载sd卡有几个途径,
卸载又是有几种方法?
一、挂载sd卡,有2种方式:
1.用户自己挂载sd卡;
2.自动挂载sd卡,这时候是在Android系统启动完成后挂载的,所以可以看成是自动挂载;

二、卸载sd卡,有2种方式:
1.用户自己卸载sd卡;
2.用户移除sd卡;
卸载sd卡,12看起来有点矛盾,但这相当于平时我们在电脑使用U盘一样,
一种是先安全删除再移除U盘;
一种是不安全删除直接移除U盘;
所以在Android系统中,卸载sd卡有两个途径:
1.Framework下发卸载命令(volume unmount sdcard force),卸载sd卡;
2.vold捕获到移除事件,如果是非安全删除sd卡,那么就卸载sd卡。

所以挂载与卸载sd卡的两种方法不同,挂载sd卡都是由Framework下发命令,而卸载sd卡则不同。

一、先来分析Framework下发卸载命令:

截取CommandListener类其中的源码:

else if (!strcmp(argv[1], "unmount")) {  
    if (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "force"))) {  
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force]", false);  
        return 0;  
    }  
     
   bool force = false;  
   if (argc >= 4 && !strcmp(argv[3], "force")) {  
       force = true;  
    }  
   rc = vm->unmountVolume(argv[2], force);  
}  

这条卸载命令的格式是:volume unmount sdcard true/false.
这里有一个强制卸载的标志,也就是force参数,如果命令包含“force”字符串,那么就强制
卸载sd卡,接下来看unmountVolume卸载函数:


int VolumeManager::unmountVolume(const char *label, bool force) {  
    Volume *v = lookupVolume(label);   
   ......  
   /*这函数清理了/mnt/asec目录的一些内容,其实看不见*/  
  cleanupAsec(v, force);  
 
   return v->unmountVol(force);  
}  

开始看卸载函数,以下函数均做简化,不再贴出大量源码,Android系统的源码实在太多:

int Volume::unmountVol(bool force) {
    /*广播sd卡正在卸载的状态*/
    setState(Volume::State_Unmounting);

    if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) {
        SLOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno));
        setState(Volume::State_Mounted);
        return -1;
    }

    if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) {
        SLOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
        goto fail_republish;
    }

    if (doUnmount(Volume::SEC_ASECDIR, force)) {
        SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR, strerror(errno));
        goto fail_remount_tmpfs;
    }
    if (doUnmount(Volume::SEC_STGDIR, force)) {
        SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno));
        goto fail_recreate_bindmount;
    }
    /*以上doMoveMount, doUnmount等函数做些清理工作,就是之前挂载到系统的目录
    清理干净*/
    /*卸载工作做完,告诉framework,该磁盘处于空闲状态*/
    setState(Volume::State_Idle);
    /*用来保存正在挂载的设备号的全局变量,现在赋为-1*/
    mCurrentlyMountedKdev = -1;
    return 0;
}

二、vold捕获移除事件,调用卸载函数:

void DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt) {
    int major = atoi(evt->findParam("MAJOR"));
    int minor = atoi(evt->findParam("MINOR"));
    char msg[255];
    int state;

    SLOGD("Volume %s %s partition %d:%d removed\n", getLabel(), getMountpoint(), major, minor);

    /*
     * The framework doesn't need to get notified of
     * partition removal unless it's mounted. Otherwise
     * the removal notification will be sent on the Disk
     * itself
     */
    state = getState();
    if (state != Volume::State_Mounted && state != Volume::State_Shared) {
        return;
    }
    /*判断,如果移除事件的设备号与正在挂载系统的设备号相等,
    说明此时是没有安全删除,所以下面会广播VolumeBadRemoval反馈码*/
    if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) {
        /*
         * Yikes, our mounted partition is going away!
         */

        snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)",
                 getLabel(), getMountpoint(), major, minor);
        mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
                                             msg, false);
        /*清理asec目录*/
        if (mVm->cleanupAsec(this, true)) {
            SLOGE("Failed to cleanup ASEC - unmount will probably fail!");
        }
        /*在这里调用了卸载函数,跟framework下发命令卸载一样。*/
        if (Volume::unmountVol(true)) {
            SLOGE("Failed to unmount volume on bad removal (%s)", 
                 strerror(errno));
            // XXX: At this point we're screwed for now
        } else {
            SLOGD("Crisis averted");
        }
    } else if (state == Volume::State_Shared) {
        /*这里的判断是,如果此时手机与电脑正在连接着使用时,移除事件的情况*/
        /* removed during mass storage */
        snprintf(msg, sizeof(msg), "Volume %s bad removal (%d:%d)",
                 getLabel(), major, minor);
        mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
                                             msg, false);
        /*卸载大容量存储*/
        if (mVm->unshareVolume(getLabel(), "ums")) {
            SLOGE("Failed to unshare volume on bad removal (%s)",
                strerror(errno));
        } else {
            SLOGD("Crisis averted");
        }
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值