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

来源:互联网 发布:配音软件 编辑:程序博客网 时间:2024/05/21 05:44
作者:gzshun. 原创作品,转载请标明出处!
来源:http://blog.csdn.net/gzshun


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

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

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

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

截取CommandListener类其中的源码:

[cpp] view plaincopy
  1. else if (!strcmp(argv[1], "unmount")) {  
  2.     if (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "force"))) {  
  3.         cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force]"false);  
  4.         return 0;  
  5.     }  
  6.       
  7.     bool force = false;  
  8.     if (argc >= 4 && !strcmp(argv[3], "force")) {  
  9.         force = true;  
  10.     }  
  11.     rc = vm->unmountVolume(argv[2], force);  
  12. }  
这条卸载命令的格式是:volume unmount sdcard true/false.
这里有一个强制卸载的标志,也就是force参数,如果命令包含“force”字符串,那么就强制
卸载sd卡,接下来看unmountVolume卸载函数:

[cpp] view plaincopy
  1. int VolumeManager::unmountVolume(const char *label, bool force) {  
  2.     Volume *v = lookupVolume(label);   
  3.     ......  
  4.     /*这函数清理了/mnt/asec目录的一些内容,其实看不见*/  
  5.     cleanupAsec(v, force);  
  6.   
  7.     return v->unmountVol(force);  
  8. }  

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

[cpp] view plaincopy
  1. int Volume::unmountVol(bool force) {  
  2.     /*广播sd卡正在卸载的状态*/  
  3.     setState(Volume::State_Unmounting);  
  4.   
  5.     if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) {  
  6.         SLOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno));  
  7.         setState(Volume::State_Mounted);  
  8.         return -1;  
  9.     }  
  10.   
  11.     if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) {  
  12.         SLOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));  
  13.         goto fail_republish;  
  14.     }  
  15.   
  16.     if (doUnmount(Volume::SEC_ASECDIR, force)) {  
  17.         SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR, strerror(errno));  
  18.         goto fail_remount_tmpfs;  
  19.     }  
  20.     if (doUnmount(Volume::SEC_STGDIR, force)) {  
  21.         SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno));  
  22.         goto fail_recreate_bindmount;  
  23.     }  
  24.     /*以上doMoveMount, doUnmount等函数做些清理工作,就是之前挂载到系统的目录 
  25.     清理干净*/  
  26.     /*卸载工作做完,告诉framework,该磁盘处于空闲状态*/  
  27.     setState(Volume::State_Idle);  
  28.     /*用来保存正在挂载的设备号的全局变量,现在赋为-1*/  
  29.     mCurrentlyMountedKdev = -1;  
  30.     return 0;  
  31. }  

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

[cpp] view plaincopy
  1. void DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt) {  
  2.     int major = atoi(evt->findParam("MAJOR"));  
  3.     int minor = atoi(evt->findParam("MINOR"));  
  4.     char msg[255];  
  5.     int state;  
  6.   
  7.     SLOGD("Volume %s %s partition %d:%d removed\n", getLabel(), getMountpoint(), major, minor);  
  8.   
  9.     /* 
  10.      * The framework doesn't need to get notified of 
  11.      * partition removal unless it's mounted. Otherwise 
  12.      * the removal notification will be sent on the Disk 
  13.      * itself 
  14.      */  
  15.     state = getState();  
  16.     if (state != Volume::State_Mounted && state != Volume::State_Shared) {  
  17.         return;  
  18.     }  
  19.     /*判断,如果移除事件的设备号与正在挂载系统的设备号相等, 
  20.     说明此时是没有安全删除,所以下面会广播VolumeBadRemoval反馈码*/  
  21.     if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) {  
  22.         /* 
  23.          * Yikes, our mounted partition is going away! 
  24.          */  
  25.   
  26.         snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)",  
  27.                  getLabel(), getMountpoint(), major, minor);  
  28.         mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,  
  29.                                              msg, false);  
  30.         /*清理asec目录*/  
  31.         if (mVm->cleanupAsec(thistrue)) {  
  32.             SLOGE("Failed to cleanup ASEC - unmount will probably fail!");  
  33.         }  
  34.         /*在这里调用了卸载函数,跟framework下发命令卸载一样。*/  
  35.         if (Volume::unmountVol(true)) {  
  36.             SLOGE("Failed to unmount volume on bad removal (%s)",   
  37.                  strerror(errno));  
  38.             // XXX: At this point we're screwed for now  
  39.         } else {  
  40.             SLOGD("Crisis averted");  
  41.         }  
  42.     } else if (state == Volume::State_Shared) {  
  43.         /*这里的判断是,如果此时手机与电脑正在连接着使用时,移除事件的情况*/  
  44.         /* removed during mass storage */  
  45.         snprintf(msg, sizeof(msg), "Volume %s bad removal (%d:%d)",  
  46.                  getLabel(), major, minor);  
  47.         mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,  
  48.                                              msg, false);  
  49.         /*卸载大容量存储*/  
  50.         if (mVm->unshareVolume(getLabel(), "ums")) {  
  51.             SLOGE("Failed to unshare volume on bad removal (%s)",  
  52.                 strerror(errno));  
  53.         } else {  
  54.             SLOGD("Crisis averted");  
  55.         }  
  56.     }  
  57. }  


卸载函数基本就这些,下一篇文章继续,格式化sd卡。。。
原创粉丝点击