[开源][交流]如何读写FAT32文件系统(9-24-2008 Updated)
本帖最后由 Gorgon_Meducer 于 2012-8-1 21:23 编辑>>写在前面的话
有待添加内容
[专题索引]
>> 磁盘引导扇区与磁盘分区表 ——如何从硬盘(U盘)中找到我们需要的分区 1楼
>> BIOS Parameter Block 与 FAT类型 ——如何区分FAT12、FAT16和FAT32 2楼
>> 磁盘分区逻辑扇区的读取 ——如何以逻辑扇区编号来访问实际的物理扇区 3楼
>> FAT32目录的访问 ——如何从指定的目录中找到想要的文件 4楼
>> 文件的存放结构 ——如何读写指定的文件 5楼
[参考文献]
A、硬盘物理结构和FAT文件系统解析(一)
B、硬盘物理结构和FAT文件系统解析(二)
[相关下载]
A、FAT32文件系统白皮书(E文原版)
B、硬盘物理结构和FAT文件系统解析ourdev_486205.pdf(文件大小:970K)
[更新日至]
更新第一章、第二章、第三章、第四章、第五章的核心代码和实例。具体讲解部
分有待补充。 本帖最后由 Gorgon_Meducer 于 2012-8-1 22:24 编辑
[磁盘引导扇区与磁盘分区表] ——如何从硬盘(U盘)中找到我们需要的分区
[原理解析]
[数据结构]
/*------------------*
* 常 数 宏 定 义*
*------------------*/
# define DPT_START_ADDRESS 0x01BE
/*------------------*
* 动 作 宏 定 义*
*------------------*/
# define DPT_PARTITION_START_SECTOR(__DPT_ITEM_ADDR) \
(__DPT_ITEM_ADDR)->RelativeSectors
/********************
*用户变量类型定义 *
********************/
typedef struct DiskPartitionTableItem DPT_ITEM;
/********************
* 结构体定义区 *
********************/
struct DiskPartitionTableItem
{
BYTE ActivePartition;
BYTE StartHead;
unsigned StartSector :6;
unsigned StartCylinder :10;
BYTE OSIndicator;
BYTE EndHead;
unsigned EndSector :6;
unsigned EndCylinder :10;
UINT32 RelativeSectors;
UINT32 TotalSectors;
};
[关键代码]
>>如何依次获取各个磁盘分区的信息
/***********************************************************
* 函数说明:获取下一个DPT项 *
* 输入: 主引导扇区指针,分区表项指针 *
* 输出: 下一个分区表项 *
* 调用函数:无 *
* -------------------------------------------------------- *
* [使用说明] *
* 当传入的分区表项指针为空(NULL)时,自动返回第 *
* 一个分区表项。当传入的分区表项指针不为空时,自动返 *
* 回下一个分区表项的指针,当下一个分区表项不存在时, *
* 返回空(NULL) *
***********************************************************/
DPT_ITEM *Get_Next_Disk_Partition
(
BYTE *pchMasterBootSector,
DPT_ITEM *pdptPartition
)
{
if (pchMasterBootSector == NULL)
{
/* 无效的输入 */
return NULL;
}
if (pdptPartition == NULL)
{
/* 要求返回第一个分区表项 */
pdptPartition = (DPT_ITEM *)(pchMasterBootSector + DPT_START_ADDRESS);
}
else
{
/* 指向下一个分区表项 */
pdptPartition += 1;
}
/* 进行分区表项的有效性检测 */
{
UINT8 n = 0;
BOOL bIfValid = FALSE;
for (n = 0;n < sizeof(DPT_ITEM);n++)
{
if (((BYTE *)pdptPartition) != 0x00)
{
bIfValid = TRUE;
break;
}
}
if (!bIfValid)
{
/* 表项为空 */
return NULL;
}
}
return pdptPartition;
}
[使用范例]
Example A:
//从引导扇区中提取第一个磁盘分区在物理扇区中的偏移量
//其中g_chSectorBuffer是一个大小为512字节的数组,保存
//了磁盘第一个引导扇区的内容
s_dwPartitionSectorOffset = DPT_PARTITION_START_SECTOR
(
Get_Next_Disk_Partition(g_chSectorBuffer,NULL)
);
Example B:
//从引导扇区中查找第一个类型为NTFS的磁盘分区,并返回
//它在物理扇区偏移量
# define OS_INDICATOR_NTFS 0x07
DPT_ITEM *pDPTItem = NULL;
do
{
//读取新的分区信息
pDPTItem = Get_Next_Disk_Partition(g_chSectorBuffer,pDPTItem);
if ((pDPTItem != NULL) && (pDPTItem->OSIndicator == OS_INDICATOR_NTFS))
{
s_dwPartitionSectorOffset =DPT_PARTITION_START_SECTOR(pDPTItem);
break;
}
}
while(pDPTItem != NULL)
if (pDPTItem != NULL)
{
//找到了需要的分区,进行对应的处理
}
else
{
//没有找到需要的分区,进行对应的处理
}
本帖最后由 Gorgon_Meducer 于 2012-8-1 22:20 编辑
——如何区分FAT12、FAT16和FAT32
<font color=blue>[原理解析]/*---------------------------------------------------------*
*[保留扇区] |启动扇区 *
*Reserved |FSINFO *
*Sectors |Root区备份(SECTOR 6) *
* -------------------------------------------------------- *
* |FAT表0 *
* |FAT表1 *
* |... (BPB_NumFATs) *
* -------------------------------------------------------- *
*|FAT16/12的根目录,FAT32不存在这个区域 *
* -------------------------------------------------------- *
*[ 数据区 ] |FAT32的根目录和数据。 *
* |需要说明的是,以第一个数据扇区为起始,簇*
* |从2开始编号。 *
*---------------------------------------------------------*/
[数据结构]
/*------------------*
* 常 数 宏 定 义*
*------------------*/
# define FAT_TYPE_FAT32 0x00
# define FAT_TYPE_FAT16 0x01
# define FAT_TYPE_FAT12 0x02
# define FAT_ERROR 0xFF
/********************
*用户变量类型定义 *
********************/
typedef struct BiosParameterBlock FAT_BPB;
/********************
* 结构体定义区 *
********************/
struct BiosParameterBlock
{
/* FAT32 Structure Starting at Offset 11 */
UINT16BPB_BytePerSec; //每扇区的字节数通常为512
UINT8 BPB_SecPerClus; //每簇的扇区数量
UINT16BPB_ResvdSecCnt; //保留扇区数
UINT8 BPB_NumFATs; //FAT表的数量
UINT16BPB_RootEntCnt; //FAT12/16根目录中目录项的项数,FAT32为0
UINT16BPB_TotSec16; //FAT12/16系统记录卷标中扇区的总数,FAT32为0
UINT8 BPB_Media; //磁盘介质
UINT16BPB_FATSz16; //FAT12/16用于保存一个FAT标所占用的扇区数
UINT16BPB_SecPerTrk; //每磁道的扇区数
UINT16BPB_NumHeads; //磁头数
UINT32BPB_HiddSec; //隐藏扇区
UINT32BPB_TotSec32; //FAT32卷中扇区的总数目
/* FAT32 Structure Starting at Offset 36 */
UINT32BPB_FATSz32; //一个FAT32表中占用的扇区数
UINT16BPB_ExtFlag; //标志位
UINT16BPB_FSVer; //FAT32 version
UINT32BPB_RootClus; //FAT32 根目录所在簇
UINT16BPB_FSInfo; //FSINFO结构体在保留扇区内的扇区号
UINT16BPB_BkBootSec; //Boot 记录的备份在保留区内的扇区号,通常为6
BYTE BPB_Reserved; //RESERVED
};
[关键代码]
>>如何判断当前的FAT文件系统类型
/*------------------*
* 动 作 宏 定 义*
*------------------*/
/* 获取根目录所占用的扇区数 */
# define GET_ROOT_DIR_SECTOR_COUNT(__BPB) \
(((__BPB).BPB_RootEntCnt * 32 + ((__BPB).BPB_BytePerSec - 1)) / (__BPB).BPB_BytePerSec)
/* 获取FAT32文件系统中第一个数据扇区的编号(位于簇2)*/
# define GET_FAT_FIRST_DATA_SECTOR(__BPB) \
(\
(__BPB).BPB_ResvdSecCnt + (__BPB).BPB_NumFATs * \
(\
((__BPB).BPB_FATSz16 != 0) ?\
(__BPB).BPB_FATSz16 : (__BPB).BPB_FATSz32\
) + GET_ROOT_DIR_SECTOR_COUNT(__BPB)\
)
/***********************************************************
* 函数说明:获取当前FAT的类型 *
* 输入: FAT_BPB指针 *
* 输出: FAT类型 *
* 调用函数:无 *
***********************************************************/
UINT8 Get_FAT_Type(FAT_BPB *pFATBPB)
{
if (pFATBPB == NULL)
{
return FAT_ERROR;
}
{
UINT32 dwTotalSectors;
if (pFATBPB->BPB_TotSec16 != 0)
{
dwTotalSectors = pFATBPB->BPB_TotSec16;
}
else
{
dwTotalSectors = pFATBPB->BPB_TotSec32;
}
dwTotalSectors -= GET_FAT_FIRST_DATA_SECTOR((*pFATBPB));
dwTotalSectors /= pFATBPB->BPB_SecPerClus;
if (dwTotalSectors < 4085)
{
return FAT_TYPE_FAT12;
}
else if (dwTotalSectors < 65525)
{
return FAT_TYPE_FAT16;
}
}
return FAT_TYPE_FAT32;
}
[使用范例]
Example A:
//判断当前的文件类型是否为FAT32,其中g_chBPBBuffer是一个
//大小为512字节的缓冲区,保存了BPB结构所在的扇区,也就是
//对应磁盘分区的逻辑0扇区中的内容。由于BPB在该扇区中的起
//始偏移为11,所以我们在需要访问BPB时需要加入相应的偏移
//量。
if (Get_FAT_Type((FAT_BPB *)(g_chBPBBuffer + 11)) != FAT_TYPE_FAT32)
{
/* 检测FAT类型是否符合要求 */
return FALSE;
] 本帖最后由 Gorgon_Meducer 于 2012-8-1 22:15 编辑
[磁盘分区逻辑扇区的读取] ——如何以逻辑扇区编号来访问实际的物理扇区
根据前面的叙述,我们知道,一个物理存储介质中可能有若干个磁盘分区,这些
磁盘分区的逻辑0扇区相对介质的物理0扇区来说,都有一个偏移量。如何在编写文件
系统的代码时,能够以磁盘分区的逻辑扇区编号来访问设备,而无需一一指名访问时
具体的物理扇区地址呢?
解决方法很简单:所有的文件系统代码在编写时,都以磁盘分区的逻辑扇区地址
为依据,也就是相对BPB所在的扇区为逻辑0扇区,然后所有针对设备的扇区读写函数
都通过一个统一的函数接口来实现,而该接口函数实际上会针对逻辑扇区的地址进行
物理地址的偏移运算,从而根据逻辑地址得到实际的物理扇区地址。
[关键代码]
//定义逻辑扇区访问接口
# define GET_SECTOR(__SECTOR_NUMBER,__BUFF_ADDR) \
Get_Sector((__SECTOR_NUMBER),(__BUFF_ADDR))//我们假设这是一个U盘设备,host_read_10_ram()会利用SCSI函数的READ_10指令读取
//U盘的指定物理扇区/***********************************************************
* 函数说明:扇区读取接口函数 *
* 输入: 要读取的扇区编号,存放扇区的缓冲区 *
* 输出: 操作是否成功 *
* 调用函数:host_read_10_ram() *
***********************************************************/
BOOL Get_Sector(UINT32 dwSectorNumber,BYTE *pBuffer)
{
if (pBuffer == NULL)
{
return FALSE;
}
host_read_10_ram
(
//还记得这个变量s_dwPartitionSectorOffset是怎么获得的么?
dwSectorNumber + s_dwPartitionSectorOffset,
pBuffer
);
return TRUE;
}[使用范例]
Example A:
//通过接口函数读取该逻辑分区的0扇区,
// 0 为逻辑扇区地址
// g_chSectorBuffer是扇区缓冲区
if (!GET_SECTOR(0,g_chSectorBuffer))
{
//扇区读取失败的处理
} 本帖最后由 Gorgon_Meducer 于 2012-8-1 21:56 编辑
——如何从指定的目录中找到想要的文件
[原理解析]
[数据结构]
/*------------------*
* 常 数 宏 定 义*
*------------------*/
# define ATTR_READ_ONLY 0x01
# define ATTR_HIDDEN 0x02
# define ATTR_SYSTEM 0x04
# define ATTR_VOLUME_ID 0x08
# define ATTR_DIRECTORY 0x10
# define ATTR_ARCHIVE 0x20
# define ATTR_LONG_NAME (ATTR_READ_ONLY |\
ATTR_HIDDEN | \
ATTR_SYSTEM | \
ATTR_VOLUME_ID)
# define FAT_ITEM_UNLOCATED 0x00000000
# define FAT_ITEM_LOCATED_LBOUND 0x00000002
# define FAT_ITEM_LOCATED_UBOUND 0xFFFFFFEF
# define FAT_ITEM_RESERVED_LBOUND 0xFFFFFFF0
# define FAT_ITEM_RESERVED_UBOUND 0xFFFFFFF6
# define FAT_ITEM_BAD_CLUSTER 0xFFFFFFF7
# define FAT_ITEM_EOC_LBOUND 0xFFFFFFF8
# define FAT_ITEM_EOC_UBOUND 0xFFFFFFFF
/*------------------*
* 动 作 宏 定 义*
*------------------*/
/* 计算出指定簇的第一个扇区的编号 */
# define GET_FIRST_SECTOR_OF_CLUSTER(__BPB,__CLUSTER) \
(((__CLUSTER) - 2) * (__BPB).BPB_SecPerClus + GET_FAT_FIRST_DATA_SECTOR(__BPB))
/********************
*用户变量类型定义 *
********************/
typedef struct FAT32DirectoryEntryFAT32_DIR_ENTRY;
/********************
* 结构体定义区 *
********************/
struct FAT32DirectoryEntry
{
BYTE DIR_Name;
UINT8 DIR_Attr;
UINT8 DIR_NTRes;
UINT8 DIR_CrtTimeTenth;
UINT16DIR_CrtTime;
UINT16DIR_CrtDate;
UINT16DIR_LstAccDate;
UINT16DIR_FstClusHI;
UINT16DIR_WrtTime;
UINT16DIR_WrtDate;
UINT16DIR_FstClusLO;
UINT32DIR_FileSize;
};
[关键代码]
>>如何从目录中获取指定编号的条目信息
/***********************************************************
* 函数说明:返回指定目录项数据 *
* 输入: BPB,目录项索引,保存目录项的缓冲区指针 *
* 输出: 保存目录项的缓冲区指针 *
* 调用函数:无 *
***********************************************************/
FAT32_DIR_ENTRY *Get_Directory_Entry_Item
(
FAT_BPB *pFATBPB,
UINT32 dwCluster,
UINT32 dwIndex,
BYTE *pchBuffer
)
{
if (
(pFATBPB == NULL)
||(pchBuffer == NULL)
||(
(dwCluster < FAT_ITEM_LOCATED_LBOUND)
&&(dwCluster> FAT_ITEM_LOCATED_UBOUND)
)
)
{
/* 无效的输入 */
return NULL;
}
{
/* 获取根目录所在的扇区 */
BYTE chSectorBuffer;
UINT32 dwDirectoryStartSector;
UINT16 wItemsPerSector;
dwDirectoryStartSector = GET_FIRST_SECTOR_OF_CLUSTER((*pFATBPB),dwCluster);
wItemsPerSector = pFATBPB->BPB_BytePerSec / sizeof(FAT32_DIR_ENTRY);
if (
!GET_SECTOR
(
dwDirectoryStartSector + (dwIndex / wItemsPerSector),
chSectorBuffer
)
)
{
/* 读取错误 */
return NULL;
}
(*(FAT32_DIR_ENTRY *)pchBuffer) =
((FAT32_DIR_ENTRY *)chSectorBuffer);
}
/* 返回结果 */
return (FAT32_DIR_ENTRY *)pchBuffer;
}
>>如何从目录指定的位置开始查找指定扩展名的文件
/***********************************************************
* 函数说明:从FAT32表中查找指定扩展名称的文件 *
* 输入: BPB指针,扩展名字符串,上一个有效目录入口*
* 输出: 是否找到需要的文件 *
* 调用函数:无 *
* -------------------------------------------------------- *
* [使用说明] *
* 输入的扩展名指针可以为空,这将导致直接从指定位 *
* 置开始向后进行遍历输出。当上一次的目录入口地址输入 *
* 为空时,则表示输出一个符合要求的结果。当找不到符合 *
* 要求的结果时,输出为NULL。 *
***********************************************************/
BOOL Find_File_Extend_Name
(
FAT_BPB *pFATBPB,
UINT32 dwCluster,
BYTE *pstrFileExterndName,
UINT32 *pdwLastEntry,
FAT32_DIR_ENTRY *pDIREntryResult
)
{
UINT32 dwSearchPoint = 0;
if (
(pFATBPB == NULL)
||(
(pdwLastEntry == NULL)
&&(pDIREntryResult == NULL)
)
)
{
/* 无效的输入 */
return FALSE;
}
if (pdwLastEntry == NULL)
{
dwSearchPoint = 0;
}
else
{
dwSearchPoint = *pdwLastEntry;
}
while(TRUE)
{
BYTE chDIREntryBuffer;
/* 获取指定的目录入口 */
FAT32_DIR_ENTRY *pDIREntry = Get_Directory_Entry_Item
(
pFATBPB,
dwCluster,
dwSearchPoint,
chDIREntryBuffer
);
if (pDIREntry == NULL)
{
/* 读取目录项失败 */
return FALSE;
}
/* 检测目录项是否有效 */
if (pDIREntry->DIR_Name == 0x00)
{
/* 已经是目录项的最后内容了 */
break;
}
else if (
(pDIREntry->DIR_Name == 0xE5)
||((pDIREntry->DIR_Attr & ATTR_LONG_NAME) == ATTR_LONG_NAME)
||((pDIREntry->DIR_Attr & ATTR_DIRECTORY) == ATTR_DIRECTORY)
)
{
/* 该目录项为空项 */
dwSearchPoint++;
continue;
}
dwSearchPoint++;
if (
pDIREntry->DIR_Name == pstrFileExterndName
&&pDIREntry->DIR_Name == pstrFileExterndName
&&pDIREntry->DIR_Name == pstrFileExterndName
)
{
/* 扩展名匹配 */
if (pdwLastEntry != NULL)
{
*pdwLastEntry = dwSearchPoint;
}
if (pDIREntryResult)
{
(*pDIREntryResult) = (*pDIREntry);
}
return TRUE;
}
}
return FALSE;
}
[使用范例]
Example A:
//列出根目录下所有的TXT文件名
//g_chBPBBuffer里面保存的是0扇区中的内容
UINT32 dwLastEntry = 0;
FAT32_DIR_ENTRY Entry = {0};
while(Find_File_Extend_Name
(
(FAT_BPB *)(g_chBPBBuffer + 11),
2,
"TXT",
&dwLastEntry,
&Entry
))
{
UINT8 n = 0;
UINT8 *pchName = Entry.DIR_Name;
for (n = 0;n < 11;n++)
{
while(!SERIAL_OUT(pchName));
}
//通过串口输出回车换行符浩
while(!SERIAL_OUT(10));
while(!SERIAL_OUT(13));
}
本帖最后由 Gorgon_Meducer 于 2012-8-1 21:52 编辑
[文件的存放结构] ——如何读写指定的文件
<font color=blue>[原理解析]
[数据结构]
[关键代码]
>>如何从文件的簇链中获取当前簇的后续簇
/***********************************************************
* 函数说明:获取当前簇的下一个簇 *
* 输入: BPB缓冲,当前簇号 *
* 输出: 下一个簇号 *
* 调用函数:无 *
***********************************************************/
static UINT32 Get_Next_Cluster(FAT_BPB *pFATBPB,UINT32 dwCluster)
{
UINT32 dwSectorNumber;
UINT16 wByteOffset;
BYTE chSectorBuffer;
dwSectorNumber = pFATBPB->BPB_ResvdSecCnt +
((dwCluster * 4) / (pFATBPB->BPB_BytePerSec));
wByteOffset = (dwCluster * 4) % (pFATBPB->BPB_BytePerSec);
/* 读取指定的扇区 */
if (!GET_SECTOR(dwSectorNumber,chSectorBuffer))
{
/* 读取错误 */
return FAT_ITEM_BAD_CLUSTER;
}
/* 获取下一个簇的簇号 */
return TYPE_CONVERSION
(
&chSectorBuffer,
UINT32
);
}
>>如何根据获取的目录项信息顺序的读取到指定的文件内容
/***********************************************************
* 函数说明:从指定的文件里面顺序读取一个扇区的数据 *
* 输入: BPB指针,文件入口地址,读写指针, *
* 存放数据的缓冲区 *
* 输出: 读取数据区的实际大小 *
* 调用函数:Get_Next_Cluster() *
* -------------------------------------------------------- *
* [使用说明] *
* 当开始一个新文件的读取时,需要通过pReadPoint将 *
* 一个0扇区编号传递给函数;其余时候,传递任何数值都*
* 将被无视,函数通过指针pReadPoint告知外部当前的读写 *
* 位置。 *
***********************************************************/
BOOL Read_File_Sectors
(
FAT_BPB *pFATBPB,
FAT32_DIR_ENTRY *pFileEntry,
UINT32 *pReadPoint,
BYTE *pchBuffer,
UINT16 *pwSize
)
{
static UINT32 s_dwReadPoint = 0;
static UINT32 s_dwRemainFileSize = 0;
static UINT32 s_dwReadCluster = 0;
static UINT8s_chInClusterSectorCounter = 0;
UINT32 dwSector = 0;
UINT16 wTempSize = 0;
if(
(pFATBPB == NULL)
||(pFileEntry == NULL)
||(pReadPoint == NULL)
||(pchBuffer == NULL)
)
{
/* 无效的输入 */
return FALSE;
}
//新文件初始化
if ((*pReadPoint) == 0)
{
s_dwReadPoint = 0; //初始化读写指针
s_chInClusterSectorCounter = 0;
s_dwRemainFileSize = pFileEntry->DIR_FileSize; //初始化剩余文件大小
//获取文件的起始簇号
s_dwReadCluster = ((UINT32)(pFileEntry->DIR_FstClusHI) << 16)
| (UINT32)(pFileEntry->DIR_FstClusLO);
}
//检查簇的合法有效性
if(
(s_dwReadCluster>= FAT_ITEM_EOC_LBOUND)
&&(s_dwReadCluster <= FAT_ITEM_EOC_UBOUND)
)
{
if (s_dwRemainFileSize == 0)
{
//正常结束
if (pwSize != NULL)
{
*pwSize = 0;
}
return TRUE;
}
else
{
//非正常结束
return FALSE;
}
}
else if (!(
(s_dwReadCluster>= FAT_ITEM_LOCATED_LBOUND)
&&(s_dwReadCluster <= FAT_ITEM_LOCATED_UBOUND)
))
{
//错误的簇信息
return FALSE;
}
if (s_dwRemainFileSize == 0)
{
//文件读写完毕
if (pwSize != NULL)
{
*pwSize = 0;
}
return TRUE;
}
//获取当前正在读取的簇的首扇区编号
dwSector = GET_FIRST_SECTOR_OF_CLUSTER(*pFATBPB,s_dwReadCluster)
+ s_chInClusterSectorCounter;
//读取扇区数据
if (!GET_SECTOR(dwSector,pchBuffer))
{
/* 读取错误 */
return FALSE;
}
//更新读写指针
s_dwReadPoint++;
s_chInClusterSectorCounter++;
if (s_chInClusterSectorCounter == pFATBPB->BPB_SecPerClus)
{
// 完成了一个簇的读取
s_chInClusterSectorCounter = 0; //复位簇内扇区读写指针
s_dwReadCluster = Get_Next_Cluster //获取下一个簇
(
pFATBPB,
s_dwReadCluster
);
}
// 返回当前的读写位置
(*pReadPoint) = s_dwReadPoint;
// 返回实际读取到的字节数
wTempSize = (s_dwRemainFileSize>= pFATBPB->BPB_BytePerSec) ?
pFATBPB->BPB_BytePerSec :
s_dwRemainFileSize;
if (pwSize != NULL)
{
*pwSize = wTempSize;
}
/* 更新完成当前读写前的剩余大小 */
s_dwRemainFileSize -= wTempSize;
return TRUE;
}
[使用范例]
Example A:
//显示根目录下所有TXT文件的文件名及文件内容
UINT32 dwLastEntry = 0;
UINT32 dwReadPoint = 0;
BYTE chBuffer;
UINT16 wSize = 0;
BYTE chBuffer;
FAT32_DIR_ENTRY Entry = {0};
while(Find_File_Extend_Name
(
(FAT_BPB *)(g_chBPBBuffer + 11),
2,
"TXT",
&dwLastEntry,
&Entry
))
{
UINT8 n = 0;
UINT8 *pchName = Entry.DIR_Name;
for (n = 0;n < 11;n++)
{
while(!SERIAL_OUT(pchName));
}
while(!SERIAL_OUT(10));
while(!SERIAL_OUT(13));
dwReadPoint = 0;
while(Read_File_Sectors
(
(FAT_BPB *)(g_chBPBBuffer + 11),
&Entry,
&dwReadPoint,
chBuffer,
&wSize
))
{
BYTE *p = chBuffer;
if (wSize == 0)
{
break;
}
while(wSize--)
{
while(!SERIAL_OUT(*p))
{
PROC_Serial_Transmitter();
}
PROC_Serial_Transmitter();
p++;
}
}
while(!SERIAL_OUT(10));
while(!SERIAL_OUT(13));
}
</font><有待添加内容> </font><有待添加内容> 哦哦哦
精品啊,重点学习
佩服 傻孩子 沉得真快啊,帮顶一下 顶!
傻孩子帖子的排版没得说! 好贴子一定要顶的,呵呵 很详细,谢谢!
前段时间我想写读取硬盘逻辑扇区的程序,发帖问了没人回答。不过我已经把程序写好了,现在的FAT程序支持1主分区+5逻辑分区的磁盘文件搜索和读取,对于137G内的硬盘来说,已达到实用阶段^_^ 顶 顶 顶 我以来收藏。 好东西,顶一顶! 学习 最后能来个完整例子,比如用AVR写个TXT文件到SD中,就完美了. 牛逼 mark 不错,记号 好贴 记号 先做个记号,毕业设计要做用ARM9实现这个功能
要细细研究~~~ mark mark 好长啊!LZ厉害 关于FAT系统,MARK 1K SRAM 的单片机玩不转这个啊。 恩,1K Sram基本不用考虑FAT系统……非要在1K SRAM的系统上跑……我只能说
很具有表演性…… mark 好贴,关于文件系统 发现自己就是个 超级菜鸟啊!!! MBR扇区的字节数是不是一定是512Bytes的?可否扩展为其它的数值?
因为我看fat手册里面是可以规定扇区字节数的,手册里面的扇区是否只是局限于该分区范围内呢?
各种资料看多了有点混乱-_- thanks. 厉害! 晕啊,怎么我看1、2楼,3、4楼,5、6楼,7,8楼的内容都是重复的?
是不是重复发了? 网站被攻击的时候,数据恢复导致的错误。别介意。 没介意,哈哈。
麻烦看一下40楼的问题,谢谢。
据说硬盘的一个扇区将来可能扩展到4kbytes,不知要怎样保证和现有硬盘的兼容性呢? 写代码的时候老老实实根据扇区大小来设置参数,而不是以默认的512字节来操作扇区就可以了。
扇区的大小应该根据BPB的内容来获取。 多谢指教。
不过BPB是VFAT FS里面才有的东西,
而我的意思是MBS(也即0柱面0磁头第一个扇区里面)是否一定是512bytes?
如果不是的话,从哪里可以得到该参数? 好资料,顶 好帖! 好帖! 好帖! 烦人啊,还有结构体的字节对齐问题。 顶 LZ强人 to 【46楼】 valley 微风山谷
准确的说法是这样的:在总共512byte的主引导记录中,MBR的引导程序占了其中的前446个字
节(偏移0H~偏移1BDH),随后的64个字节(偏移1BEH~偏移1FDH)为DPT(Disk PartitionTable,硬盘
分区表),最后的两个字节“55 AA”(偏移1FEH~偏移1FFH)是分区有效结束标志。 记号,随时关注进展 好厉害呀!
请教一个问题:我有一个台电酷闪 4G U盘,用单片机分别读取 0、1、2、3、4、5扇区(512B)时,全为零,直到第6扇区时才读到非零值,而读取爱国者(aigo 4G)正常,可以读到 0 扇区的BPB记录。用WinHEX软件读这两种 U 盘的时候都正常。是不是我没有弄清楚台电酷闪 BPB存放的正确位置,或者是物理扇区和逻辑扇区的区别? 按道理来说BPB应该是在0扇区的…… mark一下。有时间的时候看看那。 顶一个! mark 做个记号,回头重点学习。 纯mark 等能看懂的时候来看... 顶!~mark! 好资料,精品 mark 浏览过了,不错,保存下来,好好看看! mark 傻孩子的好帖 MARK A、硬盘物理结构和FAT文件系统解析(一)
B、硬盘物理结构和FAT文件系统解析(二)
好多图片打不开,楼主有办法吗? 文件系统 mark 在文件读取中
dwSectorNumber = pFATBPB->BPB_ResvdSecCnt +
((dwCluster * 4) / (pFATBPB->BPB_BytePerSec));
wByteOffset = (dwCluster * 4) % (pFATBPB->BPB_BytePerSec);
怎么理解? 谢谢。MARK mark mark 这几天在研究U盘FAT系统的文件创建与读写,怎样查询已用空间和分配新的存储空间貌似比较麻烦,不知道有什么好的方法 着几天正在用收藏了~ 傻孩子工作没有?
有这么多时间整理资料 学习学习文件系统 mark 谢谢,最近正准备做这方面的工作 mark! mark mark 顶一下。 mark 好帖 谢谢分享 做个记号 顶一下。 继续学习…标记 mark 记号!!! Mark 一下,有空来学习。 有时间在看 mark MARK mark! 好贴 mark 呵呵,我只看到mark等,有多少人实际分析!都一看都懂吗?一点疑问也没有,奇怪!呵呵 mark mark 今天才发现这个好贴,晚了,晚了 mark 顶了