读取磁盘原始扇区需严格处理权限、对齐与校验:Windows需管理员权限及FILE_SHARE_WRITE,Linux需disk组权限;MBR在LBA0,GPT头位置须通过0xEE分区定位并校验签名与CRC;必须按设备真实逻辑扇区大小(非固定512)读取,否则解析错位。

读取磁盘原始扇区需要绕过文件系统直接访问
Windows 和 Linux 对裸设备访问权限控制严格,不能直接 fopen("C:\\PhysicalDrive0", "rb") 就完事——Windows 要求管理员权限 + 打开时指定 FILE_SHARE_READ | FILE_SHARE_WRITE,且路径必须是 \\.\PhysicalDrive0;Linux 需要 /dev/sda 权限(通常得加到 disk 用户组),且普通用户默认被拒绝。跳过这步,后续所有解析都只是在读空数据或触发 Access is denied / Permission denied。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- Windows 下用
CreateFileA("\\.\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL),别漏掉双反斜杠和FILE_SHARE_WRITE(GPT 头可能跨读写校验) - Linux 下确认
ls -l /dev/sda权限,临时用sudo chmod 644 /dev/sda测试(勿长期开放) - 一律用
read()或ReadFile()读 512 字节(MBR)或 512/4096 字节(GPT LBA0),别用fscanf或带缓冲的std::ifstream—— 它们会干扰扇区对齐
MBR 分区表结构简单但字段易误读
MBR 位于 LBA 0,共 512 字节,关键区域是偏移 0x1BE 开始的 4×16 字节分区项。常见错误是把 boot_indicator(第 0 字节)当成“是否激活”,其实它只表示“是否可引导”(值为 0x80 表示活动分区),而现代 BIOS/UEFI 并不依赖它;更关键的是 start_sector(偏移 0x8,4 字节小端)和 total_sectors(偏移 0xC),这两个决定分区范围。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
uint8_t mbr[512]一次性读入,再用memcpy或位运算提取字段,避免结构体打包(#pragma pack(1)不可靠) -
partition_type(偏移0x4)值如0x07(NTFS)、0x83(Linux ext)、0xEE(GPT 容器)需查标准表,别硬编码字符串映射 - 注意 CHS 寻址字段(
0x1–0x6)已废弃,现代工具应忽略;LBA 才是唯一可信的起始/长度依据
GPT 头与分区数组位置不固定,必须校验签名
GPT 头不一定在 LBA 1 —— 它由 MBR 中的保护性 GPT 分区(type 0xEE)指向,且头本身含 header_crc32 和 first_usable_lba 字段。直接读 LBA 1 可能拿到脏数据,尤其当磁盘被部分格式化或损坏时。GPT 头签名是 ASCII 字符串 "EFI PART"(8 字节),不是 magic number 0x5452415020494645 的十六进制字面量——用 memcmp(buf, "EFI PART", 8) 比较最稳。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 先读 MBR,检查是否有 type
0xEE分区;若有,其start_sector即 GPT 头所在 LBA(通常是 1,但不可假设) - 读出疑似 GPT 头后,先验证
signature、revision(应为0x00010000)、header_crc32(需重新计算除该字段外的前 92 字节 CRC32) - 分区数组起始 LBA 是
partition_entry_lba(头中字段),每项大小固定 128 字节,数量由number_of_partition_entries给出,别硬写128 * 128
解析结果必须结合设备逻辑块大小判断有效性
同一块物理磁盘,/dev/sda 和 /dev/sda1 的 ioctl(fd, BLKSSZGET, &bs) 可能返回不同逻辑扇区大小(512 vs 4096)。GPT 规范要求头和分区数组按 LBA 对齐,但若设备报告逻辑块为 4096 字节,而你仍按 512 字节读 LBA 1,实际读到的是第 8 个 512 字节扇区——整个解析就偏了。Windows 的 IOCTL_DISK_GET_LENGTH_INFO 同样需先获取 BytesPerSector。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- Linux:调用
ioctl(fd, BLKSSZGET, §or_size)获取真实逻辑扇区大小,GPT 头读取必须按此对齐 - Windows:用
DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, ...)取Geometry.BytesPerSector - MBR 始终按 512 字节解析(历史兼容),但 GPT 必须动态适配——哪怕标称 “512e” 硬盘,固件层也可能返回 4096
分区表不是纯文本,没校验、无冗余、一字错全盘崩。别信“读出来像那么回事”——每个 CRC、每个 LBA 偏移、每个权限开关,都得亲手对上。


















