ReactOS-Freeldr磁盘及文件管理2
来源:互联网 发布:淘宝win7激活码可行么 编辑:程序博客网 时间:2024/06/06 11:00
ArcOpen的大体流程我们看过了。大致分为这几步
1. 函数会尝试找到文件所在分区的设备句柄,如果还没有对应的句柄。那么使用DEVICE.FuncTable中的Open函数打开设备,并为这个设备分配句柄。
2. 打开设备后条用XxxMount识别分区格式,识别成功返回另外的FuncTable,存储到设备的FileData.FileFuncTable域。
3. 为文件分配一个句柄,在对应的FileData.DeviceId为上面创建设备句柄,FileData.FuncTable为设备的FileData.FileFuncTable。
4. 最后调用文件的FileData.FuncTable.Open函数打开文件。
挂载分区时做了什么
之前我们忽略了XxxMount函数。现在来读读比较简单的FatMount (freeldr/freeldr/fs/fat.c)。
- const DEVVTBL* FatMount(ULONG DeviceId)
- {
- ........
- // 生成一个FAT_VOLUME_INFO结构
- Volume = MmHeapAlloc(sizeof(FAT_VOLUME_INFO));
- if (!Volume)
- return NULL;
- RtlZeroMemory(Volume, sizeof(FAT_VOLUME_INFO));
- // 读第一个扇区
- Position.HighPart = 0;
- Position.LowPart = 0;
- ret = ArcSeek(DeviceId, &Position, SeekAbsolute);
- if (ret != ESUCCESS)
- {
- MmHeapFree(Volume);
- return NULL;
- }
- ret = ArcRead(DeviceId, Buffer, sizeof(Buffer), &Count);
- if (ret != ESUCCESS || Count != sizeof(Buffer))
- {
- MmHeapFree(Volume);
- return NULL;
- }
- // 判断是否有fat分区标志
- if (!RtlEqualMemory(BootSector->FileSystemType, "FAT12 ", 8) &&
- !RtlEqualMemory(BootSector->FileSystemType, "FAT16 ", 8) &&
- !RtlEqualMemory(BootSector32->FileSystemType, "FAT32 ", 8) &&
- !RtlEqualMemory(BootSectorX->FileSystemType, "FATX", 4))
- {
- MmHeapFree(Volume);
- return NULL;
- }
- // 获得分区大小等信息
- ret = ArcGetFileInformation(DeviceId, &FileInformation);
- if (ret != ESUCCESS)
- {
- MmHeapFree(Volume);
- return NULL;
- }
- SectorCount.HighPart = FileInformation.EndingAddress.HighPart;
- SectorCount.LowPart = FileInformation.EndingAddress.LowPart;
- SectorCount.QuadPart /= SECTOR_SIZE;
- Volume->DeviceId = DeviceId;
- // 打开分区
- if (!FatOpenVolume(Volume, BootSector, SectorCount.QuadPart))
- {
- MmHeapFree(Volume);
- return NULL;
- }
- // 存储FAT_VOLUME_INFO结构
- FatVolumes[DeviceId] = Volume;
- // 返回fat文件读写的FuncTable
- return &FatFuncTable;
- }
- typedef struct _FAT_VOLUME_INFO
- {
- ULONG BytesPerSector; /* Number of bytes per sector */
- ULONG SectorsPerCluster; /* Number of sectors per cluster */
- ULONG FatSectorStart; /* Starting sector of 1st FAT table */
- ULONG ActiveFatSectorStart; /* Starting sector of active FAT table */
- ULONG NumberOfFats; /* Number of FAT tables */
- ULONG SectorsPerFat; /* Sectors per FAT table */
- ULONG RootDirSectorStart; /* Starting sector of the root directory (non-fat32) */
- ULONG RootDirSectors; /* Number of sectors of the root directory (non-fat32) */
- ULONG RootDirStartCluster; /* Starting cluster number of the root directory (fat32 only) */
- ULONG DataSectorStart; /* Starting sector of the data area */
- ULONG FatType; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */
- ULONG DeviceId;
- } FAT_VOLUME_INFO;
读取第一个山区,判断是否有fat标志。如果没有直接返回,挂载失败。之后使用ArcGetFileInformation获得分区大小。ArcGetFileInformation里面调用了FileData.FuncTable.GetFileInformation。因为当前DeviceId是设备句柄,所以他实际调用的是DiskGetFileInformation(freeldr/freeldr/arch/i386/hardware.c)。这个函数很简单,通过FileInformation返回分区开始和结束的地址,这里就不列出了。
这里的代码用FileInformation.EndingAddress / SECTOR_SIZE计算出了该分区的扇区数SectorCount。这里应该BUG。因为EndingAddress是分区结束地址,真的扇区数应该是 (分区开始地址 - EndingAddress ) / SECTOR_SIZE。好在SectorCount只是判断fat分区的一个依据,而且一般C盘计算出的SectorCount误差不会很大,影响不大。
最后执行FatOpenVolume真正执行分区的挂载、初始化。初始化结束后将生成的Volume放到fat.c维护的全局数组FatVolumes里,之后对fat分区进行操作(读写)时,通过设备的DeviceId就可以找到对应的FAT_VOLUME_INFO结构。
最后函数返回FatFuncTable函数数组
- const DEVVTBL FatFuncTable =
- {
- FatClose,
- FatGetFileInformation,
- FatOpen,
- FatRead,
- FatSeek,
- L"fastfat",
- };
- LONG FatOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
- {
- ......
- // 根据文件的FileId获得文件所在的设备句柄FileData.DeviceId, 从而获得FatMount时生成的Volume结构。
- DeviceId = FsGetDeviceId(*FileId);
- FatVolume = FatVolumes[DeviceId];
- // 从DeviceId设备中读取并查询fat表,判断path表示的文件是否存在
- RtlZeroMemory(&TempFileInfo, sizeof(TempFileInfo));
- ret = FatLookupFile(FatVolume, Path, DeviceId, &TempFileInfo);
- if (ret != ESUCCESS)
- return ENOENT;
- // 判断是否是目录
- IsDirectory = (TempFileInfo.Attributes & ATTR_DIRECTORY) != 0;
- if (IsDirectory && OpenMode != OpenDirectory)
- return EISDIR;
- else if (!IsDirectory && OpenMode != OpenReadOnly)
- return ENOTDIR;
- // 生成FAT_FILE_INFO结构,里面存放了文件的信息(开始的扇区等)
- FileHandle = MmHeapAlloc(sizeof(FAT_FILE_INFO));
- if (!FileHandle)
- return ENOMEM;
- RtlCopyMemory(FileHandle, &TempFileInfo, sizeof(FAT_FILE_INFO));
- FileHandle->Volume = FatVolume;
- // 把这个结构和文件对应的FileData.Specific关联。之后进行FatRead等操作时可以直接获得这个结构了
- FsSetDeviceSpecific(*FileId, FileHandle);
- return ESUCCESS;
- }
- ReactOS-Freeldr磁盘及文件管理2
- ReactOS-Freeldr磁盘及文件管理
- ReactOS-Freeldr内存管理
- ReactOS-Freeldr镜像加载2
- ReactOS-Freeldr注册表HIVE文件格式2
- ReactOS-Freeldr注册表HIVE文件格式2
- ReactOS-Freeldr注册表
- ReactOS-Freeldr镜像加载
- ReactOS-Freeldr注册表HIVE文件格式
- ReactOS-Freeldr注册表HIVE文件格式
- 磁盘及文件管理系统
- ReactOS-Freeldr镜像加载3
- 磁盘及文件系统管理
- 磁盘以及文件管理
- 文件与磁盘管理
- 文件管理操作的命令及原理——Linux磁盘管理及文件系统管理
- 文件及磁盘处理
- 磁盘管理2--磁盘加密
- ReactOS-Freeldr磁盘及文件管理
- 更多log4j学习资料
- 程序员如何管理好自己的思维?
- 让你上网不受限制
- Uniform中自定义按钮(Uiscript)
- ReactOS-Freeldr磁盘及文件管理2
- iterator例子程序
- jBPM开发入门指南(1)
- C/C++基础知识:函数指针和指针函数的基本概念
- struts2的环绕通知
- davinci i2c 设备注册的过程 笔记
- C++ explicit 关键字
- dbus
- ReactOS-Freeldr镜像加载