中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
作者:
标题: fat12&fat32的数据结构 上一主题 | 下一主题
fhqiugeg
新手上路





积分 18
发帖 8
注册 2008-9-6
状态 离线
『楼 主』:  fat12&fat32的数据结构

有没有人知道fat12&fat16的文件系统的数据结构的???我一直没有搞清除。看了freedos的源代码还是没有看懂。


2008-12-30 11:59
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
fhqiugeg
新手上路





积分 18
发帖 8
注册 2008-9-6
状态 离线
『第 2 楼』:  我自己看了

/* */ /* The FAT file system is difficult to trace through FAT table. */ /* There are two kinds of FAT's, 12 bit and 16 bit. The 16 bit */ /* FAT is the easiest, since it is nothing more than a series */ /* of UWORD's. The 12 bit FAT is difficult, because it packs 3 */ /* FAT entries into two BYTE's. These are packed as follows: */ /* */ /* 0x0003 0x0004 0x0005 0x0006 0x0007 0x0008 0x0009 0x0010... */ /* */ /* are packed as */ /* */ /* 0x03 0x40 0x00 0x05 0x60 0x00 0x07 0x80 0x00 0x09 0x00 0x02... */ /*请注意上面的0x0009和0x0010的fat12的表示 */ /* */ /* 12 bytes are compressed to 9 bytes */ /* (fat文件系统是很难遍历的,有两种fat,一个是12位的,一个是16位的*/ /* 16位的是很简单的,但是12位的是不通的,因为它把3个字节压缩到两个字节里了,)*/ /* 而且数据是有交叉的,第二个字节的高4位是下个簇号的低四位,第二个字节的*/ /* 第四位是第一个字节的高四位,但是仍旧是12个位表达一个文件目录*/ /*假设就是fat12文件系统,这时调用为 * * find_free_fat()-->next_cluster(dpbp,idx)->link_fat(dpbp,idx,READ_CLUSTER) * * idx是当前簇索引值,每次都是以一递增,是簇号索引。 * struct dpb *dpbp其实就是内部的驱动器的参数表,就是在每个盘最前扇区 * 的内容,来对这个驱动盘进行描述的内容结构体。 * * * 有个规定:簇是从2开始用的,前两个没有用,保留。 * * */ CLUSTER link_fat(struct dpb FAR * dpbp, CLUSTER Cluster1, REG CLUSTER Cluster2) { struct buffer FAR *bp; unsigned idx; unsigned secdiv; unsigned char wasfree = 0; CLUSTER clussec = Cluster1/*这么多簇有多少扇区*/; CLUSTER max_cluster = dpbp->dpb_size;/*最大簇号*/ #ifdef WITHFAT32 if (ISFAT32(dpbp)) max_cluster = dpbp->dpb_xsize; #endif /*当前索引的簇值肯定是要在当前盘的空间内的,如果超过了(包括两边),就返回,并报错*/ if (clussec <= 1 || clussec > max_cluster) { put_string("run CHKDSK: trying to access invalid cluster 0x"); #ifdef WITHFAT32 put_unsigned((unsigned)(clussec >> 16), 16, 4); #endif /*put_unsigned()函数是将一个十进制的字符串数转化成为2进制或者是16进制的表示方法,非常巧妙*/ put_unsigned((unsigned)(clussec & 0xffffu), 16, 4); put_console('\n'); return 1; } /*dpb->dpb_secsize是当前驱动盘的扇区大小,为什么要用secdiv做变量我还不是很清楚,可能是secctor divide *因为下面做除法了 * */ secdiv = dpbp->dpb_secsize; if (ISFAT12(dpbp)) { /*这好像要看官方文档,看 fat12的簇大小是多少的,一个簇=一个扇区=512字节,*/ /* * 这里一个2,一个3,注意的是1.5=3/2,就是一个fat要占用的字节数, * 我突然想到baidu知道上不知道是谁说fat12的簇含有4个扇区!!!!!!! * */ clussec = (unsigned)clussec * 3; secdiv *= 2; } /*暂且只讨论fat12*/ else /* FAT16 or FAT32 */ { secdiv /= 2; #ifdef WITHFAT32 if (ISFAT32(dpbp)) secdiv /= 2; #endif } /* idx is a pointer to an index which is the nibble offset of the FAT entry within the sector for FAT12, or word offset for FAT16, or dword offset for FAT32 */ /*我认为下面的代码就是计算偏移,化整为零*/ idx = (unsigned)(clussec % secdiv);/*没有构成一个扇区*/ clussec /= secdiv;/*还有多少个整数扇区*/ /*曾经做过一个计算题,好像fat表项可以是很大的,可以有几兆的*/ clussec += dpbp->dpb_fatstrt;/*绝对扇区地址*/ #ifdef WITHFAT32 if (ISFAT32(dpbp) && (dpbp->dpb_xflags & FAT_NO_MIRRORING)) { /* we must modify the active fat, it's number is in the 0-3 bits of dpb_xflags */ clussec += (dpbp->dpb_xflags & 0xf) * dpbp->dpb_xfatsize; } #endif /* Get the block that this cluster is in */ /*读一个block到一个缓冲区,返回的是缓冲区的首地址,但是比较特殊的是*/ /* 它返回的是一个512字节长度的fat表项 */ bp = getFATblock(dpbp, clussec); /*没有读成功,自然要返回,也就是读fat表项没有成功,可能是别的错误之类的*/ if (bp == NULL) return 1; /* the only error code possible here (他是说这是这个函数里面唯一的错误信息,不过好像确实是的)*/ /*针对fat12特别处理,可以看到下面每种文件系统都做了处理,我在想,如果我要加入ntfs怎么办?*/ if (ISFAT12(dpbp)) { REG UBYTE FAR *fbp0, FAR * fbp1; struct buffer FAR * bp1; unsigned cluster, cluster2; /* form an index so that we can read the block as a */ /* byte array */ /*idx上面操作得到的在簇里面的第几个扇区 * fat12文件系统一个簇=一个扇区 * * 第n个fat目录项: * n为偶数:低四位3*n/2,高四位3*n/2+1 * n为奇数:低四位 * 一个簇=??? * 一个扇区=512字节 * 一个fat表项=12位=1.5位 * * idx是在原有的簇的基础上还要移动几个扇区的索引 * 一个buffer的大小就是一个扇区的大小 * */ idx /= 2; /* Test to see if the cluster straddles the block. If */ /* it does, get the next block and use both to form the */ /* the FAT word. Otherwise, just point to the next */ /* block.(测试这个簇是否跨越了这个块,如果是这样的话,得到下个块, * 用这两个簇形成一个fat字) */ /*sizeof(b_buffer)=512B,PRI(&)>PRI(->)*/ fbp0 = &bp->b_buffer[idx]; /* pointer to next byte, will be overwritten, if not valid */ /*如果是跨越的话,就是越界的访问了吧,我的意思没有意思的访问*/ fbp1 = fbp0 + 1; /*如果这时候是跨越了的话,那么就要读下一个块,那么fbp1是无效的,而是需要重新赋值*/ /*因为是必须要读2个字节的,idx只是开始字节地址*/ if (idx >= (unsigned)dpbp->dpb_secsize - 1) { /* blockio.c LRU logic ensures that bp != bp1 (这话我还没懂,希望懂的人能解释下)*/ bp1 = getFATblock(dpbp, (unsigned)clussec + 1); if (bp1 == 0) return 1; /* the only error code possible here */ /*我看到现在只要看过READ_CLUSTER*/ if ((unsigned)Cluster2 != READ_CLUSTER) bp1->b_flag |= BFR_DIRTY | BFR_VALID; /*fbp1指向下个byte*/ fbp1 = &bp1->b_buffer[0]; } /*fbp1只是unsigned char阿?总共也就8位的,左移8位还有吗??*/ /*高高低低原则*/ cluster = *fbp0 | (*fbp1 << 8); { unsigned res = cluster; /* Now to unpack the contents of the FAT entry. Odd and */ /* even bytes are packed differently. */ /*如果要寻找的idx是奇数的话,则要*/ if (Cluster1 & 0x01) cluster >>= 4; cluster &= 0x0fff; /*因为我只要看获取一个空闲fat,所以我就看到了这里 * * 当fat项是0时候,说明是空闲的 * * */ if ((unsigned)Cluster2 == READ_CLUSTER) { if (cluster >= MASK12) return LONG_LAST_CLUSTER; if (cluster == BAD12) return LONG_BAD; return cluster; } /*如果不是在寻找空闲的fat,那么可以计算空闲的fat*/ if (cluster == FREE) wasfree++; cluster = res; } /* Cluster2 may be set to LONG_LAST_CLUSTER == 0x0FFFFFFFUL or 0xFFFF */ /* -- please don't remove this mask! */ cluster2 = (unsigned)Cluster2 & 0x0fff; /* Now pack the value in */ if (Cluster1 & 0x01) { cluster &= 0x000f; cluster2 <<= 4; } else { cluster &= 0xf000; } cluster |= cluster2; *fbp0 = (UBYTE)cluster; *fbp1 = (UBYTE)(cluster >> 8); } else if (ISFAT16(dpbp)) { /* form an index so that we can read the block as a */ /* byte array */ /* and get the cluster number */ UWORD res = fgetword(&bp->b_buffer[idx * 2]); if ((unsigned)Cluster2 == READ_CLUSTER) { if (res >= MASK16) return LONG_LAST_CLUSTER; if (res == BAD16) return LONG_BAD; return res; } /* Finally, put the word into the buffer and mark the */ /* buffer as dirty. */ fputword(&bp->b_buffer[idx * 2], (UWORD)Cluster2); if (res == FREE) wasfree++; } #ifdef WITHFAT32 else if (ISFAT32(dpbp)) { /* form an index so that we can read the block as a */ /* byte array */ UDWORD res = fgetlong(&bp->b_buffer[idx * 4]) & LONG_LAST_CLUSTER; if (Cluster2 == READ_CLUSTER) { if (res > LONG_BAD) return LONG_LAST_CLUSTER; return res; } /* Finally, put the word into the buffer and mark the */ /* buffer as dirty. */ fputlong(&bp->b_buffer[idx * 4], Cluster2 & LONG_LAST_CLUSTER); if (res == FREE) wasfree++; } #endif else return 1; /* update the free space count */ bp->b_flag |= BFR_DIRTY | BFR_VALID; if (Cluster2 == FREE || wasfree) { int adjust = 0; if (!wasfree) adjust++; else if (Cluster2 != FREE) adjust--; #ifdef WITHFAT32 if (ISFAT32(dpbp) && dpbp->dpb_xnfreeclst != XUNKNCLSTFREE) { /* update the free space count for returned */ /* cluster */ dpbp->dpb_xnfreeclst += adjust; write_fsinfo(dpbp); } else #endif if (dpbp->dpb_nfreeclst != UNKNCLSTFREE) dpbp->dpb_nfreeclst += adjust; } return SUCCESS; }


2009-1-10 18:29
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
DOSforever
金牌会员





积分 4639
发帖 2239
注册 2005-1-30
状态 离线
『第 3 楼』:  

要知道文件系统的结构根本没必要看源代码,看得也累。源代码只是用这样的数据结构而不是描述这样的数据结构。关于文件系统的数据结构有专门的资料,你可以用关键词 FAT 在论坛或网上搜索一下。




DOS倒下了,但永远不死 DOS NEVER DIES ! 投票调查: www.cn-dos.net/forum/v ... 本人尚未解决的疑难问题: www.cn-dos.net/forum/v ... www.cn-dos.net/forum/v ... www.cn-dos.net/forum/v ...
2009-1-12 21:41
查看资料  发短消息 网志   编辑帖子  回复  引用回复
guapibai
新手上路





积分 16
发帖 8
注册 2009-5-2
状态 离线
『第 4 楼』:  

good


2009-12-4 17:44
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: