2.格式化分区到指定的文件系统类型。
MBR中存放分区表的位置在446-509,占用了64字节,MBR结构只支持4个主分区,所以
有4个16字节的区域,先简要说明一下MBR的分区表的结构:
从这个表格可以看出,相对于446-509的分区表区域,每个主分区的第5个字节存放的是文件
系统标志位,用来识别什么分区,用fdisk工具查看一下,有如下文件系统对应的十六进制标志:
若需要读取这些文件系统标志,只需读取MBR的450个位置,占用一个字节大小。
扯得太远了,回到正题,本文是要分析Android格式化sd卡的功能,在格式化部分,涉及到
了系统的一些函数,与vold无关,简单的说明一下即可。
Android系统在格式化sd卡的时候,首先会判断sd卡是否存在分区,如果sd卡不存在分区,
那么需要重新初始化MBR区域,所以上面简要的介绍了MBR结构中分区表的区域。
- intVolume::formatVol(){
- if(getState()==Volume::State_NoMedia){
- errno=ENODEV;
- return-1;
- }elseif(getState()!=Volume::State_Idle){
- errno=EBUSY;
- return-1;
- }
- /*如果该分区为卸载,那么格式化失败,返回错误*/
- if(isMountpointMounted(getMountpoint())){
- SLOGW("Volumeisidlebutappearstobemounted-fixing");
- setState(Volume::State_Mounted);
- //mCurrentlyMountedKdev=XXX
- errno=EBUSY;
- return-1;
- }
- chardevicePath[255];
- dev_tdiskNode=getDiskDevice();
- dev_tpartNode;
- if(mDebug){
- SLOGI("Formattingvolume%s(%s)",getLabel(),devicePath);
- }
- setState(Volume::State_Formatting);
- if(!mLastMountedKdev){
- dev_tdeviceNodes[2];
- intn=getDeviceNodes(deviceNodes,2);
- //initializeMBRifnopartition,orhasmultiplepartitions
- //butnoneisselected
- if((diskNode==deviceNodes[0])||(n>1)){
- sprintf(devicePath,"/dev/block/vold/%d:%d",
- MAJOR(diskNode),MINOR(diskNode));
- if(initializeMbr(devicePath)){
- SLOGE("FailedtoinitializeMBR(%s)",strerror(errno));
- partNode=diskNode;//trytousewholedisk
- }else{
- partNode=MKDEV(MAJOR(diskNode),MINOR(diskNode)+1);
- }
- }else{
- partNode=deviceNodes[0];
- }
- }else{
- partNode=mLastMountedKdev;
- }
- sprintf(devicePath,"/dev/block/vold/%d:%d",
- MAJOR(partNode),MINOR(partNode));
- intret=Fat::format(devicePath,0);
- SLOGE_IF(ret,"Failedtoformat(%s)",strerror(errno));
- setState(Volume::State_Idle);
- returnret;
- }
格式化函数两个主要工作交给了initializeMbr和Fat::format函数:
1.initializeMbr函数负责初始化MBR;
2.Fat::format函数负责格式化分区。
先来看initializeMbr函数的初始化工作:
- intVolume::initializeMbr(constchar*deviceNode){
- structdisk_infodinfo;
- memset(&dinfo,0,sizeof(dinfo));
- if(!(dinfo.part_lst=(structpart_info*)malloc(MAX_NUM_PARTS*sizeof(structpart_info)))){
- SLOGE("Failedtomallocprt_lst");
- return-1;
- }
- memset(dinfo.part_lst,0,MAX_NUM_PARTS*sizeof(structpart_info));
- dinfo.device=strdup(deviceNode);
- dinfo.scheme=PART_SCHEME_MBR;
- dinfo.sect_size=512;
- dinfo.skip_lba=2048;
- dinfo.num_lba=0;
- dinfo.num_parts=1;
- structpart_info*pinfo=&dinfo.part_lst[0];
- pinfo->name=strdup("android_sdcard");
- pinfo->flags|=PART_ACTIVE_FLAG;
- pinfo->type=PC_PART_TYPE_FAT32;
- pinfo->len_kb=-1;
- intrc=apply_disk_config(&dinfo,0);
- if(rc){
- SLOGE("Failedtoapplydiskconfiguration(%d)",rc);
- gotoout;
- }
- out:
- free(pinfo->name);
- free(dinfo.device);
- free(dinfo.part_lst);
- returnrc;
- }
这里贴出一些重要的结构体:
- structpart_info{
- char*name;
- uint8_tflags;
- uint8_ttype;
- uint32_tlen_kb;/*in1K-bytes*/
- uint32_tstart_lba;/*theLBAwherethispartitionbegins*/
- };
- structdisk_info{
- char*device;
- uint8_tscheme;
- intsect_size;/*expectedsectorsizeinbytes.MUSTBEPOWEROF2*/
- uint32_tskip_lba;/*insectors(1unitofLBA)*/
- uint32_tnum_lba;/*thesizeofthediskinLBAunits*/
- structpart_info*part_lst;
- intnum_parts;
- };
初始化完成后,将该结构体变量pinfo通过apply_disk_config函数进行设置:
- intapply_disk_config(structdisk_info*dinfo,inttest)
- {
- intfd;
- structwrite_list*wr_lst=NULL;
- intrv;
- if(validate_and_config(dinfo,&fd,&wr_lst)!=0){
- LOGE("Configurationisinvalid.");
- gotofail;
- }
- if((rv=wlist_commit(fd,wr_lst,test))>=0)
- rv=test?0:sync_ptable(fd);
- close(fd);
- wlist_free(wr_lst);
- returnrv;
- fail:
- close(fd);
- if(wr_lst)
- wlist_free(wr_lst);
- return1;
- }
该函数先打开sd卡的设备节点,然后将MBR的初始化信息写到第一个block(512B)中,
这里涉及到非常多函数,不在vold的讨论范围。
写完MBR后,就要对分区进行格式化,要格式化成FAT32格式,Fat::format函数直接调用
系统命令newfs_msdos来格式化新分区,检测磁盘是,Fat::check函数直接调用系统命令
fsck_msdos来检测分区。
最后格式化完成功,通知Framework,sd卡处于空闲状态:
- setState(Volume::State_Idle);
然后,Framework又要重复挂载和卸载的操作了。