Android-vold源码分析之格式化SD卡(10)

13 篇文章 0 订阅
作者:gzshun. 原创作品,转载请标明出处!
来源:http://blog.csdn.net/gzshun


本文开始讨论sd卡的格式化功能,平时使用windows操作系统,也经常格式化磁盘。涉及到的
操作有这几步:
1.将分区信息写到硬盘的第一个设备节点的MBR结构中的分区表;
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结构中分区表的区域。

[cpp]  view plain copy
  1. int Volume::formatVol() {  
  2.     if (getState() == Volume::State_NoMedia) {  
  3.         errno = ENODEV;  
  4.         return -1;  
  5.     } else if (getState() != Volume::State_Idle) {  
  6.         errno = EBUSY;  
  7.         return -1;  
  8.     }  
  9.     /*如果该分区为卸载,那么格式化失败,返回错误*/  
  10.     if (isMountpointMounted(getMountpoint())) {  
  11.         SLOGW("Volume is idle but appears to be mounted - fixing");  
  12.         setState(Volume::State_Mounted);  
  13.         // mCurrentlyMountedKdev = XXX  
  14.         errno = EBUSY;  
  15.         return -1;  
  16.     }  
  17.   
  18.     char devicePath[255];  
  19.     dev_t diskNode = getDiskDevice();  
  20.     dev_t partNode;  
  21.   
  22.     if (mDebug) {  
  23.         SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);  
  24.     }  
  25.     setState(Volume::State_Formatting);  
  26.   
  27.     if (!mLastMountedKdev) {  
  28.         dev_t deviceNodes[2];  
  29.         int n = getDeviceNodes(deviceNodes, 2);  
  30.         // initialize MBR if no partition, or has multiple partitions  
  31.         // but none is selected  
  32.         if ((diskNode == deviceNodes[0]) || (n > 1)) {  
  33.             sprintf(devicePath, "/dev/block/vold/%d:%d",  
  34.                     MAJOR(diskNode), MINOR(diskNode));  
  35.             if (initializeMbr(devicePath)) {  
  36.                 SLOGE("Failed to initialize MBR (%s)", strerror(errno));  
  37.                 partNode = diskNode; // try to use whole disk  
  38.             } else {  
  39.                 partNode = MKDEV(MAJOR(diskNode), MINOR(diskNode) + 1);  
  40.             }  
  41.         } else {  
  42.             partNode = deviceNodes[0];  
  43.         }  
  44.     } else {  
  45.         partNode = mLastMountedKdev;  
  46.     }  
  47.   
  48.     sprintf(devicePath, "/dev/block/vold/%d:%d",  
  49.             MAJOR(partNode), MINOR(partNode));  
  50.   
  51.     int ret = Fat::format(devicePath, 0);  
  52.     SLOGE_IF(ret, "Failed to format (%s)", strerror(errno));  
  53.   
  54.     setState(Volume::State_Idle);  
  55.     return ret;  
  56. }  

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

[cpp]  view plain copy
  1. int Volume::initializeMbr(const char *deviceNode) {  
  2.     struct disk_info dinfo;  
  3.   
  4.     memset(&dinfo, 0, sizeof(dinfo));  
  5.   
  6.     if (!(dinfo.part_lst = (struct part_info *) malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {  
  7.         SLOGE("Failed to malloc prt_lst");  
  8.         return -1;  
  9.     }  
  10.   
  11.     memset(dinfo.part_lst, 0, MAX_NUM_PARTS * sizeof(struct part_info));  
  12.     dinfo.device = strdup(deviceNode);  
  13.     dinfo.scheme = PART_SCHEME_MBR;  
  14.     dinfo.sect_size = 512;  
  15.     dinfo.skip_lba = 2048;  
  16.     dinfo.num_lba = 0;  
  17.     dinfo.num_parts = 1;  
  18.   
  19.     struct part_info *pinfo = &dinfo.part_lst[0];  
  20.   
  21.     pinfo->name = strdup("android_sdcard");  
  22.     pinfo->flags |= PART_ACTIVE_FLAG;  
  23.     pinfo->type = PC_PART_TYPE_FAT32;  
  24.     pinfo->len_kb = -1;  
  25.   
  26.     int rc = apply_disk_config(&dinfo, 0);  
  27.   
  28.     if (rc) {  
  29.         SLOGE("Failed to apply disk configuration (%d)", rc);  
  30.         goto out;  
  31.     }  
  32.   
  33.  out:  
  34.     free(pinfo->name);  
  35.     free(dinfo.device);  
  36.     free(dinfo.part_lst);  
  37.   
  38.     return rc;  
  39. }  

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

[cpp]  view plain copy
  1. struct part_info {  
  2.     char *name;  
  3.     uint8_t flags;  
  4.     uint8_t type;  
  5.     uint32_t len_kb;       /* in 1K-bytes */  
  6.     uint32_t start_lba;    /* the LBA where this partition begins */  
  7. };  
  8. struct disk_info {  
  9.     char *device;  
  10.     uint8_t scheme;  
  11.     int sect_size;       /* expected sector size in bytes. MUST BE POWER OF 2 */  
  12.     uint32_t skip_lba;   /* in sectors (1 unit of LBA) */  
  13.     uint32_t num_lba;    /* the size of the disk in LBA units */  
  14.     struct part_info *part_lst;  
  15.     int num_parts;  
  16. };  

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

[cpp]  view plain copy
  1. int apply_disk_config(struct disk_info *dinfo, int test)  
  2. {  
  3.     int fd;  
  4.     struct write_list *wr_lst = NULL;  
  5.     int rv;  
  6.   
  7.     if (validate_and_config(dinfo, &fd, &wr_lst) != 0) {  
  8.         LOGE("Configuration is invalid.");  
  9.         goto fail;  
  10.     }  
  11.   
  12.     if ((rv = wlist_commit(fd, wr_lst, test)) >= 0)  
  13.         rv = test ? 0 : sync_ptable(fd);  
  14.   
  15.     close(fd);  
  16.     wlist_free(wr_lst);  
  17.     return rv;  
  18.   
  19. fail:  
  20.     close(fd);  
  21.     if (wr_lst)  
  22.         wlist_free(wr_lst);  
  23.     return 1;  
  24. }  

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

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

然后,Framework又要重复挂载和卸载的操作了。
下篇文章介绍Android系统与电脑的连接,OTG功能,全称on-the-go。
待续。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值