FAT32文件系统学习(1) —— BPB的理解

FAT 32 文件系统学习

1、本文的目标

本文将通过实际读取一个FAT32格式的U盘来简单了解和学习FAT32文件系统的格式。虽然目前windwos操作系统的主流文件系统格式是NTFS,但是FAT32由于其兼容性原因,还是有一定的学习价值。为了能做出一个窗体程序提供直观的感觉,本文的代码采用c#编写,对应的c++代码也会附上。

2、本文目录

1、本文的目标

2、什么是FAT32

3、引导区

2、什么是FAT32

FAT32是Windwos系统硬盘格式分区的一种。这种格式采用32位的文件分配表,使其对磁盘的管理能力大大增强,突破了FAT16对配一个分区的容量只有2GB的限制。虽然目前已被更优异的NTFS分区格式所取代[1]。其实说白了就是FAT表的每一项长度都是32位,所以叫做FAT32。至于每一项存放的内容是什么,下面的内容会慢慢进行分析。

  • FAT32的构成

FAT32 文件系统将逻辑盘的空间划分为三部分,依次是引导区 (BOOT区)、文件分配表区(FAT区)、数据区(DATA区)[2]。引导区和文件分配表区又合称为系统区。本文将简单学习引导区的内容,文件分配表区和数据区将在下一篇文章中学习。

3、引导区

引导区从第一扇区开始,保存了每个扇区的字节数,一个簇的扇区数,FAT表的起始位置,FAT表的个数以及FAT表的扇区数等信息。之后还留有若干保留扇区。首先我们先看一下如何从一个U盘当中读取引导区(这里只读取第一个扇区,接下来的读取方法相同)。为了直接读取磁盘的逻辑扇区,我们需要用到windows api当中的几个函数,分别是CreateFile(这里用来创建磁盘的句柄),ReadFile(这里用于读取磁盘扇区)。首先来看一下这两个函数的定义:

1 HANDLE WINAPI CreateFile(
2   _In_      LPCTSTR lpFileName,                          // 要打开的文件的名或设备名。
3   _In_      DWORD dwDesiredAccess,                       // 指定类型的访问对象。
4   _In_      DWORD dwShareMode,                           // 文件共享模式
5   _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // 定义了文件的安全特性
6   _In_      DWORD dwCreationDisposition,
7   _In_      DWORD dwFlagsAndAttributes,
8   _In_opt_  HANDLE hTemplateFile                         // 返回句柄
9 );

这个函数在msnd上可以查到,这里需要说明一下的是,dwShareMode需要指定为FILE_SHARE_WRITE才能读取扇区的数据(这里是为什么我也不太清楚为什么,希望高人指教)。dwCreationDisposition需要制定为OPEN_EXISTING ,表示文件必须已经存在,由设备提出要求。函数如执行成功,则返回文件句柄。否则返回的句柄 = INVALID_HANDLE_VALUE表示出错,会设置GetLastError。具体失败原因可以查询ErrorCode。

第二个函数是ReadFile,其定义如下:

1 BOOL ReadFile(
2     HANDLE hFile,               //文件的句柄
3     LPVOIDl pBuffer,            //用于保存读入数据的一个缓冲区
4     DWORD nNumberOfBytesToRead, //要读入的字节数
5     LPDWORD lpNumberOfBytesRead,//指向实际读取字节数的指针
6     LPOVERLAPPED lpOverlapped
7     //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参  数引用一个特殊的结构。
8     //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
9 );

该函数用于读取文件,这里指的是读取U盘扇区。其中lpOverlapped设为NULL即可。需要特别注意的是,由于磁盘是以扇区为单位进行读写的,所以这里读取的字节数必须是512的倍数!其他参数注释写的很明白,这里就不再解释了。配合SetFilePointer函数可以读取指定起始位置上指定字节的数据。

首先先来看一下用c++是如何读取引导扇区的数据的。

 1     // 笔者的U盘盘符为G
 2     WCHAR szDiscFile[] = _T("\\\\.\\G:");
 3     // 打开设备句柄
 4     HANDLE hDisc = CreateFile(szDiscFile, GENERIC_READ,  FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 5     if (hDisc == INVALID_HANDLE_VALUE)
 6     {
 7         // 打开设备失败
 8         return 0;
 9     }
10     // 从第一个扇区起始位置开始读取
11     SetFilePointer(hDisc, 0, 0, FILE_BEGIN);
12     // 需要读取字节数
13     DWORD dwNumber2Read = 512;
14     // 实际读取的字节数
15     DWORD dwRealNumber;
16     // 分配缓冲区
17     char* buffer = new char[512];
18     bool bRet = ReadFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL);
19
20     // 扫尾工作,释放缓冲区,关闭句柄
21     delete[] buffer;
22     CloseHandle(hDisc);

如果我们在21行处下各断点的话可以看到buffer在内存中的数据,这里为了方便,笔者直接把这512个字节的数据保存到了文件中,用二进制文件读取软件打开来看了下,部分数据如下图所示:

  • BPB参数

好了,接下来重点来了。首先,最开始的3各字节的数据分别是跳转指令与空指令,因为在汇编当中0xEB是跳转指令,0x58是跳转的地址,而0x90则是空指令。至于为什么要在这里放上一句跳转指令呢,这个还得从启动区开始讲起,为了节约篇幅,我就简单介绍一下:一般第一个扇区叫做启动区,cpu把扇区当中的数据当作指令来执行,当读取到EB 58 这个指令时,遍跳转到0x58这个地址并继续读取指令来执行,而0x58地址之后的内容通常都是载入操作系统的指令。如果希望知道详细内容的读者不妨去看一下《30天自制操作系统》这本书,第一天结尾部分有很详细的说明。总之这边的话FAT32规定这个3各字节的内容必须是EB 58 90,只要记住就行了(笑)。

而从0x03~0x0A这9个字节的数据表示OEM,这里即为“MSDOS5.0”。

我们把从0x000B开始的79个字节的数据叫做BPB(BIOS Paramter Block),关于BPB的详细说明请参见下表[5]

BPB参数信息
偏移量 字节数 含义
0x00B 2 每扇区字数 0x0200
0x00D 1 每簇扇区数 0x08
0x00E 2 保留扇区数 0x03F8
0x010 1  FAT个数  0x02
0x011 2 根目录项数,FAT32以突破该限制,无效  0x0000 
0x013 2 扇区总数,小于32M使用  0x0000 
0x015 1 存储介质描述负  0x0F8 
0x016 2 每FAT表占用扇区数 ,小于32M使用 0x0000 
0x018 2 逻辑每磁道扇区数  0x003F 
0x01A 2 逻辑磁头数   0x00FF
0x01C 4 系统隐含扇区数   0x00000080
0x020 4 扇区总数,大于32M使用   0x00784F80
0x024 4 每FAT表扇区数,大于32M使用  0x00001E04 
0x028 2 标记  0x0000
0x02A 2 版本 (通常为零) 0x0000
0x02C 4 根目录起始簇  0x00000002 
0x030 2 Boot占用扇区数  0x0001 
0x032 2 备份引导扇区位置  0x0006
0x034 14 保留 14个字节的0x00 
0x042 1 扩展引导标记  0x29 
0x043 4 序列号  0x6A9C4125 
0x047 10 卷标 转成字符即“NO NAME”
0x052 8 文件系统  转成字符即“FAT32” 

为了用窗体程序直观的显示各个参数,接下来把上面的程序改写为c#。众所周知,c#调用系统函数大多都需要靠间接调用c的动态库来实现,这里的CreateFile和ReadFile也不例外。下面我们先编写一个FileReader类来提供这些系统api调用。部分代码如下,完整的FileReader点我下载

class FileReader
{
  [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
    static extern unsafe System.IntPtr CreateFile
    (
        string FileName,          // file name
        uint DesiredAccess,       // access mode
        uint ShareMode,           // share mode
        uint SecurityAttributes,  // Security Attributes
        uint CreationDisposition, // how to create
        uint FlagsAndAttributes,  // file attributes
        int hTemplateFile         // handle to template file
    );
  public bool Open(string FileName)
    {
        // open the existing file for reading
        handle = CreateFile
        (
            FileName,
            GENERIC_READ,
            FILE_SHARE_WRITE,
            0,
            OPEN_EXISTING,
            0,
            0
        );

        if (handle != System.IntPtr.Zero)
        {
            return true;
        }
        else
        {
            return false;
        }
    }}

由于本文的重点不是学习c#窗体编程,所以略过这部分,直接通过调用FileReader提供的系统API并编写窗体程序,效果如下图所示(本程序参考[3]),需要完整工程的读者可以点我下载,请我VS2012及以上打开。

好了,今天这篇文章就先写到这边。由于本人才疏学浅,对于FAT32也是刚开始学习,如果有错误的地方欢迎批评指正。同时这也是我第一次发随笔,如果排版等方面有不妥的地方也欢迎提出。接下来会继续学习接下去的FAT表区和数据区并继续更新接下来的学习心得。

参考文献:

1、http://baike.baidu.com/view/45233.htm?fr=aladdin

2、FAT32文件格式 http://blog.csdn.net/shrekmu/article/details/5950414

3、读写U盘(FAT32)引导扇区 http://blog.csdn.net/zhanglei8893/article/details/5912903

4、F?A?T?3?2?文?件?系?统?格?式?详?解 http://wenku.baidu.com/link?url=zrGv8nld-bc-7KT_TKbo2vWplaiIHhmJ9_ydRZBZdZ4zy8odQFwS6komz2gz1AHX36T_EN1CKZ_16d19upW9pDauno6zEmpw10wlTSTwcoi

5、基?于?U?盘?F?A?T?3?2?文?件?系?统?的?分?析 http://wenku.baidu.com/link?url=cIKgrwV66y4CoyuOEB1-OhjRY9tnXtIAoZuYEwDCjxbyRomSIiJgBAXGxq6LudfwuopUpYhiVd8TjxrBFoVyPs0NX3OqbnoWjyn4ZAx60Wi

FAT32文件系统学习(1) —— BPB的理解,布布扣,bubuko.com

时间: 2024-10-26 15:42:16

FAT32文件系统学习(1) —— BPB的理解的相关文章

FAT32文件系统学习(3) —— 数据区(DATA区)

FAT32文件系统学习(3) —— 数据区(DATA区) 今天继续学习FAT32文件系统的数据区部分(Data区).其实这一篇应该是最有意思的,我们可以通过在U盘内放入一些文件,然后在程序中读取出来:反过来也可以用程序在U盘内写入一下数据,然后在windows下可以看到写入的文件.这些笔者都会在这篇文章中演示.同时,在写这篇文章的时候笔者也发现了许多意想不到的规律. 1.本文目录 1.读取根目录 2.短文件名目录项 3.长文件名目录项 4.U盘写入文件夹 5.参考文献 2.读取根目录 两张FAT

FAT32文件系统学习(2) —— FAT表

1.题外话 在继续本文学习FAT32文件系统之前,先来插入一点别的话题.我们都知道U盘有一个属性是容量,就拿笔者的U盘为例,笔者手上的U盘是金士顿的DataTraveler G3 4GB的一个U盘.电脑上显示的容量如图1所示为3.75GB.那么这个3.75GB是怎么计算出来的呢? 图 1 系统显示U盘属性 我们先来回顾一下上一篇BPB参数当中的Sectors(扇区总数)这个参数,这一参数代表了这个U盘在出厂时的总扇区数,笔者手上这个是7884672个,可以从图2中看到.其中每个扇区为512 B,

入门级:理解FAT32文件系统(转载翻译)

FAT(File Allocation Table ) 这个网页的目的是帮助你理解怎么样在微软FAT32文件系统下取得数据,处理的硬盘的大小通常在500M到几百G之间.FAT是一个相对简单和纯净的文件系统.大多数文件系统都支持FAT,包括Linux和MacOS.所以也是需要访问硬盘的底层固件项目的常用文件系统.FAT16和FAT12是适用于小硬盘的小文件系统.这个网页将只重点介绍FAT32,和简单地比较一下他们的不同之处. 但是,这个网页的内容故意掩盖了很多细节和省略了很多这个文件系统出色的地方

【转载】FAT32文件系统详解

硬盘是用来存储数据的,为了使用和管理方便,这些数据以文件的形式存储在硬盘上.任何操作系统都有自己的文件管理系统,不同的文件系统又有各自不同的逻辑组织方式.例如:常见的文件系统有FAT,NTFS,EXT,UFS,HFS+等等.作者后面的文章会一一讲到,下面就来学习一下基于Windows的FAT32文件系统. FAT32文件系统由DBR及其保留扇区,FAT1,FAT2 和 DATA 四个部分组成,其机构如下图: 这些结构是在分区被格式化时创建出来的,含义解释如下: DBR及其保留扇区:DBR的含义是

Unix文件系统学习笔记之二: 文件描述符、inode和打开文件表

Unix文件系统学习笔记之二: 文件描述符.inode和打开文件表 系统盘上数据的布局 文件系统无非是关于数据在磁盘上的组织以及存储空间管理的,为此,首先需要知道磁盘上数据的总体布局方式.以Unix为例,最重要的一张表如下: Unix 进程管理中和用户文件.io 最相关的数据结构:usr 数据结构 The procstructure does not record information related to file access.  However the userstructure con

FAT32文件系统--For TF卡

1. TF卡空间是如何分配的? 下面以4GB TF卡为例,通过WinHex工具进行分析,其空间分配如下图所示: FAT32把目录当做文件来管理,所以没有独立的目录区,所有的文件目录项都是在数据区里面的. 2. 启动扇区 (DBR) DBR(DOS BOOT RECORD,DOS引导记录),位于柱面0,磁头1,扇区1,即逻辑扇区0 ;    DBR包括: •  一个引导程序: DOS 引导程序完成DOS系统文件(IO.SYS,MSDOS.SYS)的定位与装载 • 一个BPB:  BPB用来描述本D

FAT32文件系统的存储组织结构(一)

对磁盘的物理结构,逻辑结构和存储结构有了比较深入的了解后,我们来仔细探讨FAT32文件系统的存储组织结构.说到文件系统的组织结构,我们应该马上意识到,这指的是文件系统在同一个分区内的组织结构,在这个话题上,我们完全可以不管分区之外的所有事情. 为了分析FAT32文件系统的存储组织结构,我们来建立一个实实在在的文件系统:将U盘插入电脑,将U盘格式化成FAT32分区格式: 以建好的U盘FAT32文件系统为基础,下面从文件系统的各个组成来分别加以介绍. 分区引导扇区DBR 用winhex打开U盘显示如

linux ext2 文件系统学习

Linux  ext2文件系统理解 硬盘组成: 硬盘由多个圆形硬盘片组成.按照硬盘片能够容纳的数据量分为单盘和多盘.硬盘的数据读取主要靠机械手臂上的磁头,在机械手臂上有多个磁头.机械手臂不动硬盘旋转一周划过的路径就是磁道.由于在一块硬盘上有多个硬盘片重叠放置,所以在硬盘旋转的时候在不同硬盘片上画出了多个相同的磁道,这些相同的磁道组成了柱面.柱面是分区的最小单位.由圆形向外画直线又可以将磁道划分为扇区,扇区是数据存储的最小单位,一个扇区的大小约为512字节. 磁盘容量 = 柱面 * 磁头 * 扇区

ASP.NET知识重新梳理(二)------关于ASP.NET知识学习流程的一些理解

ASP.NET知识的学习流程我大概是这么理解的,首先我们必须打好C#的基础,若是之前没有学过C++之类的面向对象语言作为基础,还是要好好看看继承派生多态之类的区别和联系的:其次,当今的编程不仅仅只是我们在学校课堂上所学的控制台应用程序,我们还要学习winfom,WPF之类的本地窗体应用:第三,每个公司的技术方向都是不同的,但是共同的地方是都需要数据库来存储自己的数据,而且sqlserver,mysql,oracle都是大同小异的,所以如果你之前的编程学的不是很好,做一个DBA吧,入门难度也不是很