`
yidongkaifa
  • 浏览: 4052069 次
文章分类
社区版块
存档分类
最新评论

Android-vold源码分析之卸载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类其中的源码:

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

  1. intVolumeManager::unmountVolume(constchar*label,boolforce){
  2. Volume*v=lookupVolume(label);
  3. ......
  4. /*这函数清理了/mnt/asec目录的一些内容,其实看不见*/
  5. cleanupAsec(v,force);
  6. returnv->unmountVol(force);
  7. }

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

  1. intVolume::unmountVol(boolforce){
  2. /*广播sd卡正在卸载的状态*/
  3. setState(Volume::State_Unmounting);
  4. if(doMoveMount(getMountpoint(),SEC_STGDIR,force)){
  5. SLOGE("Failedtomovemount%s=>%s(%s)",getMountpoint(),SEC_STGDIR,strerror(errno));
  6. setState(Volume::State_Mounted);
  7. return-1;
  8. }
  9. if(doUnmount(Volume::SEC_STG_SECIMGDIR,force)){
  10. SLOGE("Failedtounmounttmpfson%s(%s)",SEC_STG_SECIMGDIR,strerror(errno));
  11. gotofail_republish;
  12. }
  13. if(doUnmount(Volume::SEC_ASECDIR,force)){
  14. SLOGE("Failedtoremovebindmounton%s(%s)",SEC_ASECDIR,strerror(errno));
  15. gotofail_remount_tmpfs;
  16. }
  17. if(doUnmount(Volume::SEC_STGDIR,force)){
  18. SLOGE("Failedtounmount%s(%s)",SEC_STGDIR,strerror(errno));
  19. gotofail_recreate_bindmount;
  20. }
  21. /*以上doMoveMount,doUnmount等函数做些清理工作,就是之前挂载到系统的目录
  22. 清理干净*/
  23. /*卸载工作做完,告诉framework,该磁盘处于空闲状态*/
  24. setState(Volume::State_Idle);
  25. /*用来保存正在挂载的设备号的全局变量,现在赋为-1*/
  26. mCurrentlyMountedKdev=-1;
  27. return0;
  28. }

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

  1. voidDirectVolume::handlePartitionRemoved(constchar*devpath,NetlinkEvent*evt){
  2. intmajor=atoi(evt->findParam("MAJOR"));
  3. intminor=atoi(evt->findParam("MINOR"));
  4. charmsg[255];
  5. intstate;
  6. SLOGD("Volume%s%spartition%d:%dremoved\n",getLabel(),getMountpoint(),major,minor);
  7. /*
  8. *Theframeworkdoesn'tneedtogetnotifiedof
  9. *partitionremovalunlessit'smounted.Otherwise
  10. *theremovalnotificationwillbesentontheDisk
  11. *itself
  12. */
  13. state=getState();
  14. if(state!=Volume::State_Mounted&&state!=Volume::State_Shared){
  15. return;
  16. }
  17. /*判断,如果移除事件的设备号与正在挂载系统的设备号相等,
  18. 说明此时是没有安全删除,所以下面会广播VolumeBadRemoval反馈码*/
  19. if((dev_t)MKDEV(major,minor)==mCurrentlyMountedKdev){
  20. /*
  21. *Yikes,ourmountedpartitionisgoingaway!
  22. */
  23. snprintf(msg,sizeof(msg),"Volume%s%sbadremoval(%d:%d)",
  24. getLabel(),getMountpoint(),major,minor);
  25. mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
  26. msg,false);
  27. /*清理asec目录*/
  28. if(mVm->cleanupAsec(this,true)){
  29. SLOGE("FailedtocleanupASEC-unmountwillprobablyfail!");
  30. }
  31. /*在这里调用了卸载函数,跟framework下发命令卸载一样。*/
  32. if(Volume::unmountVol(true)){
  33. SLOGE("Failedtounmountvolumeonbadremoval(%s)",
  34. strerror(errno));
  35. //XXX:Atthispointwe'rescrewedfornow
  36. }else{
  37. SLOGD("Crisisaverted");
  38. }
  39. }elseif(state==Volume::State_Shared){
  40. /*这里的判断是,如果此时手机与电脑正在连接着使用时,移除事件的情况*/
  41. /*removedduringmassstorage*/
  42. snprintf(msg,sizeof(msg),"Volume%sbadremoval(%d:%d)",
  43. getLabel(),major,minor);
  44. mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
  45. msg,false);
  46. /*卸载大容量存储*/
  47. if(mVm->unshareVolume(getLabel(),"ums")){
  48. SLOGE("Failedtounsharevolumeonbadremoval(%s)",
  49. strerror(errno));
  50. }else{
  51. SLOGD("Crisisaverted");
  52. }
  53. }
  54. }

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics