1.将分区信息写到硬盘的第一个设备节点的MBR结构中的分区表;
2.格式化分区到指定的文件系统类型。

MBR中存放分区表的位置在446-509,占用了64字节,MBR结构只支持4个主分区,所以

有4个16字节的区域,先简要说明一下MBR的分区表的结构:

Android-vold源码分析之格式化SD卡
从这个表格可以看出,相对于446-509的分区表区域,每个主分区的第5个字节存放的是文件
系统标志位,用来识别什么分区,用fdisk工具查看一下,有如下文件系统对应的十六进制标志:

Android-vold源码分析之格式化SD卡
若需要读取这些文件系统标志,只需读取MBR的450个位置,占用一个字节大小。

扯得太远了,回到正题,本文是要分析Android格式化sd卡的功能,在格式化部分,涉及到
了系统的一些函数,与vold无关,简单的说明一下即可。
Android系统在格式化sd卡的时候,首先会判断sd卡是否存在分区,如果sd卡不存在分区,
那么需要重新初始化MBR区域,所以上面简要的介绍了MBR结构中分区表的区域。

  1. intVolume::formatVol(){
  2. if(getState()==Volume::State_NoMedia){
  3. errno=ENODEV;
  4. return-1;
  5. }elseif(getState()!=Volume::State_Idle){
  6. errno=EBUSY;
  7. return-1;
  8. }
  9. /*如果该分区为卸载,那么格式化失败,返回错误*/
  10. if(isMountpointMounted(getMountpoint())){
  11. SLOGW("Volumeisidlebutappearstobemounted-fixing");
  12. setState(Volume::State_Mounted);
  13. //mCurrentlyMountedKdev=XXX
  14. errno=EBUSY;
  15. return-1;
  16. }
  17. chardevicePath[255];
  18. dev_tdiskNode=getDiskDevice();
  19. dev_tpartNode;
  20. if(mDebug){
  21. SLOGI("Formattingvolume%s(%s)",getLabel(),devicePath);
  22. }
  23. setState(Volume::State_Formatting);
  24. if(!mLastMountedKdev){
  25. dev_tdeviceNodes[2];
  26. intn=getDeviceNodes(deviceNodes,2);
  27. //initializeMBRifnopartition,orhasmultiplepartitions
  28. //butnoneisselected
  29. if((diskNode==deviceNodes[0])||(n>1)){
  30. sprintf(devicePath,"/dev/block/vold/%d:%d",
  31. MAJOR(diskNode),MINOR(diskNode));
  32. if(initializeMbr(devicePath)){
  33. SLOGE("FailedtoinitializeMBR(%s)",strerror(errno));
  34. partNode=diskNode;//trytousewholedisk
  35. }else{
  36. partNode=MKDEV(MAJOR(diskNode),MINOR(diskNode)+1);
  37. }
  38. }else{
  39. partNode=deviceNodes[0];
  40. }
  41. }else{
  42. partNode=mLastMountedKdev;
  43. }
  44. sprintf(devicePath,"/dev/block/vold/%d:%d",
  45. MAJOR(partNode),MINOR(partNode));
  46. intret=Fat::format(devicePath,0);
  47. SLOGE_IF(ret,"Failedtoformat(%s)",strerror(errno));
  48. setState(Volume::State_Idle);
  49. returnret;
  50. }

格式化函数两个主要工作交给了initializeMbr和Fat::format函数:
1.initializeMbr函数负责初始化MBR;
2.Fat::format函数负责格式化分区。
先来看initializeMbr函数的初始化工作:

  1. intVolume::initializeMbr(constchar*deviceNode){
  2. structdisk_infodinfo;
  3. memset(&dinfo,0,sizeof(dinfo));
  4. if(!(dinfo.part_lst=(structpart_info*)malloc(MAX_NUM_PARTS*sizeof(structpart_info)))){
  5. SLOGE("Failedtomallocprt_lst");
  6. return-1;
  7. }
  8. memset(dinfo.part_lst,0,MAX_NUM_PARTS*sizeof(structpart_info));
  9. dinfo.device=strdup(deviceNode);
  10. dinfo.scheme=PART_SCHEME_MBR;
  11. dinfo.sect_size=512;
  12. dinfo.skip_lba=2048;
  13. dinfo.num_lba=0;
  14. dinfo.num_parts=1;
  15. structpart_info*pinfo=&dinfo.part_lst[0];
  16. pinfo->name=strdup("android_sdcard");
  17. pinfo->flags|=PART_ACTIVE_FLAG;
  18. pinfo->type=PC_PART_TYPE_FAT32;
  19. pinfo->len_kb=-1;
  20. intrc=apply_disk_config(&dinfo,0);
  21. if(rc){
  22. SLOGE("Failedtoapplydiskconfiguration(%d)",rc);
  23. gotoout;
  24. }
  25. out:
  26. free(pinfo->name);
  27. free(dinfo.device);
  28. free(dinfo.part_lst);
  29. returnrc;
  30. }

这里贴出一些重要的结构体:

  1. structpart_info{
  2. char*name;
  3. uint8_tflags;
  4. uint8_ttype;
  5. uint32_tlen_kb;/*in1K-bytes*/
  6. uint32_tstart_lba;/*theLBAwherethispartitionbegins*/
  7. };
  8. structdisk_info{
  9. char*device;
  10. uint8_tscheme;
  11. intsect_size;/*expectedsectorsizeinbytes.MUSTBEPOWEROF2*/
  12. uint32_tskip_lba;/*insectors(1unitofLBA)*/
  13. uint32_tnum_lba;/*thesizeofthediskinLBAunits*/
  14. structpart_info*part_lst;
  15. intnum_parts;
  16. };

初始化完成后,将该结构体变量pinfo通过apply_disk_config函数进行设置:

  1. intapply_disk_config(structdisk_info*dinfo,inttest)
  2. {
  3. intfd;
  4. structwrite_list*wr_lst=NULL;
  5. intrv;
  6. if(validate_and_config(dinfo,&fd,&wr_lst)!=0){
  7. LOGE("Configurationisinvalid.");
  8. gotofail;
  9. }
  10. if((rv=wlist_commit(fd,wr_lst,test))>=0)
  11. rv=test?0:sync_ptable(fd);
  12. close(fd);
  13. wlist_free(wr_lst);
  14. returnrv;
  15. fail:
  16. close(fd);
  17. if(wr_lst)
  18. wlist_free(wr_lst);
  19. return1;
  20. }

该函数先打开sd卡的设备节点,然后将MBR的初始化信息写到第一个block(512B)中,
这里涉及到非常多函数,不在vold的讨论范围。
写完MBR后,就要对分区进行格式化,要格式化成FAT32格式,Fat::format函数直接调用
系统命令newfs_msdos来格式化新分区,检测磁盘是,Fat::check函数直接调用系统命令
fsck_msdos来检测分区。

最后格式化完成功,通知Framework,sd卡处于空闲状态:
  1. setState(Volume::State_Idle);

然后,Framework又要重复挂载和卸载的操作了。

相关文章: