exfat文件系统(六)------exfat_get_block详解

来源:互联网 发布:淘宝限时抢购怎么弄 编辑:程序博客网 时间:2024/05/19 09:09

        从上一篇的exfat文件系统(五)中,我们可以了解到exfat文件系统的读写都需要一个重要的函数exfat_get_block,而对exfat_get_block的功能的作用需要从mpage_readpage的函数来理解,从学习中,我们可以发现exfat_get_block的主要功能是检查page上所有的物理块是否连续,然后配合mpage_readpage提交bio操作。以下详细分析学习和研究过程。

        在学习mpage_readpage函数时,发现网络上有一篇文章很好的介绍了该函数的功能。转摘博客:http://blog.chinaunix.net/uid-28236237-id-4028521.html

        mpage_readpage调用到do_mpage_readpage


do_mpage_readpage详解如下:

/* 
 * This is the worker routine which does all the work of mapping the disk 
 * blocks and constructs largest possible bios, submits them for IO if the 
 * blocks are not contiguous on the disk. 
 * 
 * We pass a buffer_head back and forth and use its buffer_mapped() flag to 
 * represent the validity of its disk mapping and to decide when to do the next 
 * get_block() call. 
 */ 
 
/*这个函数试图读取文件中的一个page大小的数据,最理想的情况下就是这个page大小 
的数据都是在连续的物理磁盘上面的,然后函数只需要提交一个bio请求就可以获取 
所有的数据,这个函数大部分工作在检查page上所有的物理块是否连续,检查的方法 
就是调用文件系统提供的get_block函数,如果不连续,需要调用block_read_full_page 
函数采用buffer 缓冲区的形式来逐个块获取数据*/ 
/* 
    1、调用get_block函数检查page中是不是所有的物理块都连续 
    2、如果连续调用mpage_bio_submit函数请求整个page的数据 
    3、如果不连续调用block_read_full_page逐个block读取 
*/ 
static struct bio * 
do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, 
                  sector_t *last_block_in_bio, struct buffer_head *map_bh, 
                  unsigned long *first_logical_block, get_block_t get_block) 

    struct inode *inode = page->mapping->host; 
    const unsigned blkbits = inode->i_blkbits; 
    const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits; 
    const unsigned blocksize = 1 << blkbits; 
    sector_t block_in_file; 
    sector_t last_block; 
    sector_t last_block_in_file; 
    sector_t blocks[MAX_BUF_PER_PAGE]; 
    unsigned page_block; 
    unsigned first_hole = blocks_per_page; 
    struct block_device *bdev = NULL; 
    int length; 
    int fully_mapped = 1
    unsigned nblocks; 
    unsigned relative_block; 
 
    if (page_has_buffers(page)) 
        goto confused; 
    /* 
    block_in_file 本page中的第一个block number 
    last_block 本page中最后一个block 的大小 
    last_block_in_file 文件大小求出文件的最后一个block 大小*/ 
    block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits); 
    last_block = block_in_file + nr_pages *blocks_per_page; 
    last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits; 
 
    /*last_block 最后等于本次对这个page操作的最后一个block大小*/ 
    if (last_block > last_block_in_file) 
        last_block = last_block_in_file; 
    page_block = 0
 
    /* 
     * Map blocks using the result from the previous get_blocks call first. 
     */ 
    nblocks = map_bh->b_size >> blkbits; 
    /*对于普通情况mpage_readpage调用下,map_bh只是一个临时变量不会走到 
    下面的分支*/ 
    if (buffer_mapped(map_bh) && block_in_file > *first_logical_block && 
            block_in_file < (*first_logical_block + nblocks)) 
    { 
        unsigned map_offset = block_in_file - *first_logical_block; 
        unsigned last = nblocks - map_offset; 
 
        for (relative_block = 0; ; relative_block++) 
        { 
            if (relative_block == last) 
            { 
                clear_buffer_mapped(map_bh); 
                break
            } 
            if (page_block == blocks_per_page) 
                break
            blocks[page_block] = map_bh->b_blocknr + map_offset + 
                                 relative_block; 
            page_block++; 
            block_in_file++; 
        } 
        bdev = map_bh->b_bdev; 
    } 
 
    /* 
     * Then do more get_blocks calls until we are done with this page. 
     */ 
    map_bh->b_page = page; 
    /*这个循环是比较关键的路径,理解这个函数至关重要 
    1、page_block从0开始循环,它表示在这个page内的block大小 
    2、调用get_block  函数查找对应逻辑块的物理块号是多少 
    3、如果遇到了文件空洞、page上的物理块不连续就会跳转到confused 
    4、将这个page中每个逻辑块对应的物理块都保存到临时的数组blocks[] 中*/ 
    while (page_block < blocks_per_page) 
    { 
        map_bh->b_state = 0
        map_bh->b_size = 0
        //遍历页面中的块数
        if (block_in_file < last_block) 
        { 
            map_bh->b_size = (last_block - block_in_file) << blkbits; 

      //将文件中的块号转换成bh
            if (get_block(inode, block_in_file, map_bh, 0)) 
                goto confused; 
            *first_logical_block = block_in_file; 
        } 
       //bh没有被映射,可能是一个文件空洞
        if (!buffer_mapped(map_bh)) 
        { 
            fully_mapped = 0
            if (first_hole == blocks_per_page) 
                first_hole = page_block; 
            page_block++; 
            block_in_file++; 
            continue
        } 
 
        /* some filesystems will copy data into the page during 
         * the get_block call, in which case we don't want to 
         * read it again.  map_buffer_to_page copies the data 
         * we just collected from get_block into the page's buffers 
         * so readpage doesn't have to repeat the get_block call 
         */ 

    //如果块缓存区是最新的,将其数据直接copy到page
        if (buffer_uptodate(map_bh)) 
        { 
            map_buffer_to_page(page, map_bh, page_block); 
            goto confused; 
        } 
 
        if (first_hole != blocks_per_page) 
            goto confused;        /* hole -> non-hole */ 
 
        /* Contiguous blocks? */ 

    //判断请求的块缓存是不是连续的。如果不连续,就跳转到confused
        if (page_block && blocks[page_block-1] != map_bh->b_blocknr - 1
            goto confused; 
        nblocks = map_bh->b_size >> blkbits; 
        for (relative_block = 0; ; relative_block++) 
        { 
            if (relative_block == nblocks) 
            { 
                clear_buffer_mapped(map_bh); 
                break
            } 
            else if (page_block == blocks_per_page) 
                break
            blocks[page_block] = map_bh->b_blocknr + relative_block; 
            page_block++; 
            block_in_file++; 
        } 
        bdev = map_bh->b_bdev; 
    } 
 
    /*如果发现文件中有洞,将整个page清0,因为文件洞的区域 
    物理层不会真的去磁盘上读取,必须在这里主动清零,否则 
    文件洞区域内容可能随机*/ 
    if (first_hole != blocks_per_page) 
    { 
        zero_user_segment(page, first_hole << blkbits, PAGE_CACHE_SIZE); 
        if (first_hole == 0
        { 
            SetPageUptodate(page); 
            unlock_page(page); 
            goto out; 
        } 
    } 
    else if (fully_mapped) 
    { 
        SetPageMappedToDisk(page); 
    } 
 
    /* 
     * This page will go to BIO.  Do we need to send this BIO off first? 
     */ 
    /*bio 为NULL,目前分析的场景可以跳过去*/ 
    if (bio && (*last_block_in_bio != blocks[0] - 1)) 
        bio = mpage_bio_submit(READ, bio); 
 
alloc_new: 
    if (bio == NULL) 
    { 
        /*重新分配一个bio结构体 
        blocks[0] << (blkbits - 9) 这个是page中第一个逻辑块的物理块号, 
        转换成物理扇区号*/ 
        bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), 
                          min_t(int, nr_pages, bio_get_nr_vecs(bdev)), 
                          GFP_KERNEL); 
        if (bio == NULL) 
            goto confused; 
    } 
 
    length = first_hole << blkbits; 
    if (bio_add_page(bio, page, length, 0) < length) 
    { 
        bio = mpage_bio_submit(READ, bio); 
        goto alloc_new; 
    } 
 
    relative_block = block_in_file - *first_logical_block; 
    nblocks = map_bh->b_size >> blkbits; 
    if ((buffer_boundary(map_bh) && relative_block == nblocks) || 
            (first_hole != blocks_per_page)) 
        bio = mpage_bio_submit(READ, bio); 
    else 
        *last_block_in_bio = blocks[blocks_per_page - 1]; 
out: 
    /*一切顺利,整个page中的物理块是相连的,返回一个bio*/ 
    return bio; 
 
confused: 
    if (bio) 
        bio = mpage_bio_submit(READ, bio); 
    /*page 中的物理块不相连,没有办法一个一个buffer去读取出来 
    */ 
    if (!PageUptodate(page)) 
        block_read_full_page(page, get_block); 
    else 
        unlock_page(page); 
    goto out; 


网络上找到一个介绍缓存的说明如下:

linux在读写文件的时候会先将文件逻辑映射到页面逻辑,然后会在页高速缓存中寻找文件的数据,如果找到,那么对于读操作,那么就将数据直接返回给用户,如果对于缓冲写操作,那么会将数据写到这个页高速缓存中的页面,如果没有在页高速缓存找到页面,那么会分配一个页面加入到页高速缓存,然后着手IO操作,即使不是没有在页高速缓存找到页面而是找到的页面不是uptodate的页面,那么也要着手IO,怎么IO呢,这就是涉及到2.6内核的一个新特性的新实现,这就是mpage,其实就是页面的io操作,具体实现就要用到bio结构了,vfs子系统会在页高速缓存的需要io的页面上循环进行操作,怎么操作呢,就是将一个页面分割为多个“逻辑块”,然后构造一个bio,将一个页面加入到这个bio,这样循环中的每一个页面都会加入到这个bio,最后,统一用mpage_bio_submit来提交io操作

exfat_get_block就是现实“linux在读写文件的时候会先将文件逻辑映射到页面逻辑,然后会在页高速缓存中寻找文件的数据,如果找到,那么对于读操作,那么就将数据直接返回给用户,如果对于缓冲写操作,那么会将数据写到这个页高速缓存中的页面,如果没有在页高速缓存找到页面,那么会分配一个页面加入到页高速缓存”的操作(简单的就是说,该函数将相对于文件起始的块号转换为文件系统的逻辑块号)。这样继续看exfat_get_block的代码就比较明白了。

exfat_get_block的详细流程图如下:



在学习exfat_get_block的代码中,我采用测试程序读方式来跟踪log,简单的读数据时,ffsMapCluster的debug log如下:

enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 1 now *clu = 3723

进入文件管家,播放一段视频(其中有暂停,快进和循环播放操作),log(部分)如下:

<6>[ 2534.253607] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 1 now *clu = 3723
<6>[ 2729.367136] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 652 now *clu = 3071
<6>[ 2729.972564] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 652 now *clu = 3071
<6>[ 2729.972739] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 652 now *clu = 3071
<6>[ 2729.972773] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 1, num_clusters = 652 now *clu = 3071
<6>[ 2736.333772] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 312 now *clu = 62722
<6>[ 2736.343226] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 0, num_clusters = 312 now *clu = 62722
<6>[ 2736.343289] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 1, num_clusters = 312 now *clu = 62722
<6>[ 2736.343516] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 1, num_clusters = 312 now *clu = 62722
<6>[ 2736.343565] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 2, num_clusters = 312 now *clu = 62722
<6>[ 2736.343627] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 3, num_clusters = 312 now *clu = 62722
<6>[ 2736.354171] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 3, num_clusters = 312 now *clu = 62722
<6>[ 2736.354232] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 4, num_clusters = 312 now *clu = 62722
<6>[ 2736.354300] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 5, num_clusters = 312 now *clu = 62722
<6>[ 2736.354361] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 6, num_clusters = 312 now *clu = 62722
<6>[ 2736.354427] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 7, num_clusters = 312 now *clu = 62722
<6>[ 2736.357080] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 7, num_clusters = 312 now *clu = 62722
<6>[ 2736.357145] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 8, num_clusters = 312 now *clu = 62722
<6>[ 2736.357215] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 9, num_clusters = 312 now *clu = 62722
<6>[ 2736.357276] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 10, num_clusters = 312 now *clu = 62722
<6>[ 2736.357338] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 11, num_clusters = 312 now *clu = 62722
<6>[ 2736.374826] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 11, num_clusters = 312 now *clu = 62722
<6>[ 2736.374894] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 12, num_clusters = 312 now *clu = 62722
<6>[ 2736.374969] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 13, num_clusters = 312 now *clu = 62722
<6>[ 2736.375037] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 14, num_clusters = 312 now *clu = 62722
<6>[ 2736.375100] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 15, num_clusters = 312 now *clu = 62722
<6>[ 2736.393375] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 15, num_clusters = 312 now *clu = 62722
<6>[ 2736.393443] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 16, num_clusters = 312 now *clu = 62722
<6>[ 2736.393510] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 17, num_clusters = 312 now *clu = 62722
<6>[ 2736.393974] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 18, num_clusters = 312 now *clu = 62722
<6>[ 2736.394047] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 19, num_clusters = 312 now *clu = 62722
<6>[ 2736.414981] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 19, num_clusters = 312 now *clu = 62722
<6>[ 2736.415049] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 20, num_clusters = 312 now *clu = 62722
<6>[ 2736.415120] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 21, num_clusters = 312 now *clu = 62722
<6>[ 2736.415183] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 22, num_clusters = 312 now *clu = 62722
<6>[ 2736.415246] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 23, num_clusters = 312 now *clu = 62722
<6>[ 2736.435625] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 23, num_clusters = 312 now *clu = 62722
<6>[ 2736.435696] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 24, num_clusters = 312 now *clu = 62722
<6>[ 2736.435820] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 25, num_clusters = 312 now *clu = 62722
<6>[ 2736.435885] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 26, num_clusters = 312 now *clu = 62722
<6>[ 2736.435951] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 27, num_clusters = 312 now *clu = 62722
<6>[ 2736.458553] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 27, num_clusters = 312 now *clu = 62722
<6>[ 2736.458621] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 28, num_clusters = 312 now *clu = 62722
<6>[ 2736.458691] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 29, num_clusters = 312 now *clu = 62722
<6>[ 2736.458755] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 30, num_clusters = 312 now *clu = 62722
<6>[ 2736.458820] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 31, num_clusters = 312 now *clu = 62722
<6>[ 2736.478704] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 31, num_clusters = 312 now *clu = 62722
<6>[ 2736.478773] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 32, num_clusters = 312 now *clu = 62722
<6>[ 2736.478842] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 33, num_clusters = 312 now *clu = 62722
<6>[ 2736.478909] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 34, num_clusters = 312 now *clu = 62722
<6>[ 2736.478973] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 35, num_clusters = 312 now *clu = 62722
<6>[ 2736.499001] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 35, num_clusters = 312 now *clu = 62722
<6>[ 2736.499068] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 36, num_clusters = 312 now *clu = 62722
<6>[ 2736.499140] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 37, num_clusters = 312 now *clu = 62722
<6>[ 2736.499206] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 38, num_clusters = 312 now *clu = 62722
<6>[ 2736.499273] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 39, num_clusters = 312 now *clu = 62722
<6>[ 2736.519611] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 39, num_clusters = 312 now *clu = 62722
<6>[ 2736.519677] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 40, num_clusters = 312 now *clu = 62722
<6>[ 2736.519744] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 41, num_clusters = 312 now *clu = 62722
<6>[ 2736.519809] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 42, num_clusters = 312 now *clu = 62722
<6>[ 2736.519873] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 43, num_clusters = 312 now *clu = 62722
<6>[ 2736.540243] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 43, num_clusters = 312 now *clu = 62722
<6>[ 2736.540312] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 44, num_clusters = 312 now *clu = 62722
<6>[ 2736.540388] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 45, num_clusters = 312 now *clu = 62722
<6>[ 2736.540454] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 46, num_clusters = 312 now *clu = 62722
<6>[ 2736.540519] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 47, num_clusters = 312 now *clu = 62722
<6>[ 2736.560914] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 47, num_clusters = 312 now *clu = 62722
<6>[ 2736.560982] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 48, num_clusters = 312 now *clu = 62722
<6>[ 2736.561051] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 49, num_clusters = 312 now *clu = 62722
<6>[ 2736.561166] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 50, num_clusters = 312 now *clu = 62722
<6>[ 2736.561230] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 51, num_clusters = 312 now *clu = 62722
<6>[ 2736.580953] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 51, num_clusters = 312 now *clu = 62722
<6>[ 2736.581020] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 52, num_clusters = 312 now *clu = 62722
<6>[ 2736.581087] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 53, num_clusters = 312 now *clu = 62722
<6>[ 2736.581150] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 54, num_clusters = 312 now *clu = 62722
<6>[ 2736.581214] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 55, num_clusters = 312 now *clu = 62722
<6>[ 2736.600991] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 55, num_clusters = 312 now *clu = 62722
<6>[ 2736.601055] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 56, num_clusters = 312 now *clu = 62722
<6>[ 2736.601120] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 57, num_clusters = 312 now *clu = 62722
<6>[ 2736.601185] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 58, num_clusters = 312 now *clu = 62722
<6>[ 2736.601245] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 59, num_clusters = 312 now *clu = 62722
<6>[ 2736.620800] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 59, num_clusters = 312 now *clu = 62722
<6>[ 2736.620867] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 60, num_clusters = 312 now *clu = 62722
<6>[ 2736.620989] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 61, num_clusters = 312 now *clu = 62722
<6>[ 2736.621053] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 62, num_clusters = 312 now *clu = 62722
<6>[ 2736.621121] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 63, num_clusters = 312 now *clu = 62722
<6>[ 2736.641751] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 63, num_clusters = 312 now *clu = 62722
<6>[ 2736.641824] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 64, num_clusters = 312 now *clu = 62722
<6>[ 2736.641894] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 65, num_clusters = 312 now *clu = 62722
<6>[ 2736.641958] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 66, num_clusters = 312 now *clu = 62722
<6>[ 2736.642032] enter [ffsMapCluster] fid->flags = 0x 3 clu_offset = 67, num_clusters = 312 now *clu = 62722


到此为止,基本理解exfat读过程。




0 0
原创粉丝点击