fdisk原理与实战:Linux磁盘分区底层工具详解
1. 为什么今天还要学 fdisk——一个被低估却不可替代的分区基石工具你可能已经用过lsblk看磁盘布局用过parted做 GPT 分区甚至在图形界面里点几下就完成了分区操作。但只要你在 Linux 下真正做过服务器部署、嵌入式系统烧录、数据恢复现场响应或者调试过一块新到的 NVMe SSD 在 CentOS 7 上识别异常的问题你就一定会回到那个黑底白字、没有鼠标、只有光标闪烁的fdisk界面。它不炫酷不自动不带进度条但它像一把瑞士军刀里的主刀片——小硬准且从不撒谎。fdisk 的核心价值从来不是“多好用”而是“多可靠”。它直接与内核的块设备层对话绕过所有抽象层和缓存逻辑所见即所得。当你执行fdisk /dev/sdb它读取的是磁盘 MBR 或 DOS 兼容区域的真实扇区数据当你敲下w写入它调用的是ioctl(BLKRRPART)系统调用强制内核重新读取分区表——这个动作比任何 GUI 工具点击“应用”都更底层、更确定。这也是为什么在 Kali Linux 渗透测试中当目标主机磁盘出现分区表损坏时fdisk -l是第一个被调用的诊断命令为什么在国产 Linux 发行版如统信 UOS、麒麟 Kylin的安装镜像里即使提供了图形化分区器其底层仍默认调用fdisk做兼容性兜底为什么面试官问“如何安全清空一块 SSD 的分区信息”答案永远是fdisk /dev/nvme0n1→d全删→w而不是rm -rf /dev/nvme0n1p*——后者只是删设备节点分区表还在盘上重启后又会复活。我做过三年一线运维处理过 200 台物理服务器的磁盘初始化。最常遇到的场景不是“不会分”而是“分错了不敢动”。比如某次给一台 Dell R730 加装 4TB SATA 盘RAID 卡 BIOS 里设成了 JBOD 模式但系统识别成/dev/sdb而lsblk显示它已有两个隐藏分区厂商预置的诊断分区。这时候parted会报错“无法识别分区类型”GParted 直接灰掉“删除”按钮——但fdisk /dev/sdb进去一看p打印出来清清楚楚/dev/sdb1类型0x12Compaq Diagnostics/dev/sdb2类型0xeeGPT 容器。两行d命令就能干掉w保存后parted立刻恢复正常。这种“看得见、删得掉、改得准”的确定性就是 fdisk 不可替代的底气。它不解决所有问题但它永远是你排查分区类问题的第一站——就像医生不会跳过听诊器直接上 CT。2. fdisk 的设计哲学与底层逻辑为什么它长这样2.1 交互式命令行的本质不是“软件”而是“协议终端”很多人把fdisk当成一个普通命令其实它更接近一个“磁盘分区协议的交互式终端”。它的设计完全遵循 PC BIOS 时代的 MBRMaster Boot Record规范而这个规范至今仍是 x86 架构下最广泛兼容的分区标准。MBR 结构极其简单512 字节的引导扇区前 446 字节是引导代码接着是 64 字节的分区表4 个 16 字节条目最后 2 字节是魔数0x55AA。fdisk的所有操作本质上都是在读写这 64 字节的内存映像并在写入时校验魔数、计算 CHS 地址柱面-磁头-扇区、验证起始扇区对齐——这些细节GUI 工具早已帮你屏蔽但fdisk把它们全部摊开给你看。举个典型例子当你输入n创建新分区时fdisk会问Partition type p primary (default) e extended Select (default p):这里的选择不是“功能差异”而是物理结构约束。MBR 规范只允许最多 4 个主分区primary或 3 个主分区 1 个扩展分区extended而扩展分区内部可以再划出多个逻辑分区logical。fdisk强制你做这个选择是因为它必须严格按 MBR 格式生成分区表条目——选p就往主分区槽位写选e就占用一个主槽位来指向扩展分区起始位置。如果你强行想建第 5 个主分区fdisk会直接拒绝“No free sectors available in the selected region.”——这不是软件限制是硬件规范铁律。再看单位问题。fdisk默认显示和输入的单位是“扇区”sector通常是 512 字节。但你会看到提示“First sector (2048-83886079, default 2048):”。为什么默认从 2048 开始因为现代硬盘尤其是 Advanced Format 4K 扇区盘要求分区起始对齐到 1MB 边界2048×5121MB否则性能暴跌。fdisk不解释“为什么是 2048”它只告诉你“这是合法范围”逼你去查文档——这种“不友好”恰恰是它尊重硬件真实性的体现。2.2 与 parted/gdisk 的根本区别抽象层级决定适用场景特性fdiskpartedgdisk目标分区表MBRDOSMBR/GPT抽象层GPT原生单位默认扇区512BMB/GB用户友好扇区但支持 MiB/GiB交互模式命令驱动d/p/n/w命令脚本混合类 fdisk 但支持 GPT 专属命令安全性机制无内存缓存w才写盘内存缓存quit时才确认写入同 parted但 GPT 备份头校验更严典型使用场景服务器初始化、故障恢复、嵌入式刷机日常桌面分区、脚本自动化新式 UEFI 系统、大容量磁盘2TB关键点在于parted是一个“分区管理抽象层”它把 MBR 和 GPT 当作不同后端向上提供统一接口而fdisk是“MBR 专用协议终端”它不抽象只忠实实现 MBR 规范。所以当你在 CentOS 7 上用parted /dev/sdb mkpart primary ext4 0% 100%它背后可能调用fdisk写 MBR也可能调用sg_write_buffer写 GPT——你不知道也不需要知道。但如果你要确保某块盘绝对用 MBR比如为老 BIOS 主板装系统fdisk是唯一能让你 100% 确认分区表类型和结构的工具。提示fdisk -l输出中如果看到 “Disk label type: dos”说明是 MBR如果是 “gpt”那其实是fdisk在兼容模式下读取 GPT此时它无法编辑 GPT 分区会提示 “GPT PMBR size mismatch”必须换gdisk。这个细节常被忽略却是判断工具是否“真正生效”的第一关。2.3 为什么“主分区右键没有删除字样”——GUI 工具的权限与抽象陷阱网络热词里反复出现“主分区右键没有删除字样”这绝不是 bug而是 GUI 工具如 GParted、Disks的主动保护策略。它们在检测到以下任一情况时会禁用删除按钮分区已挂载mount | grep /dev/sdb1有输出分区是根文件系统findmnt /返回该设备分区包含 LVM PV 或 RAID 成员pvs/mdadm --detail /dev/sdb1有结果分区类型为0x12Compaq Diagnostics、0xefEFI System等系统保留类型而fdisk没有这些检查——它只管分区表结构。你可以对一个正在挂载的/dev/sdb1执行d删除w写入后内核会立刻失效该设备节点lsblk立刻消失但如果你没先umount正在读写的进程会收到I/O error并可能崩溃。GUI 工具的“不能删”是帮你规避风险fdisk的“能删”是给你终极控制权——代价是你要自己承担后果。这就是专业工具的分水岭前者是保姆后者是手术刀。3. fdisk 实操全流程详解从零开始创建、编辑、删除、显示分区3.1 准备工作识别目标磁盘与安全前提在执行任何fdisk操作前必须完成三件事缺一不可第一步确认目标磁盘设备名# 查看所有块设备及其大小排除 loop 设备和 dm-* lsblk -d -o NAME,SIZE,RO,TYPE,MOUNTPOINT # 更精确地过滤物理磁盘排除 NVMe 的命名空间和 USB 设备 sudo lshw -class disk -short | grep -E (disk|storage) | grep -v loop\|nvme.*n1\|usb # 关键验证确认该盘未被 LVM/RAID 占用 sudo pvs # 应无该盘输出 sudo vgs # 应无相关卷组 sudo mdadm --detail --scan | grep -q /dev/sdb echo WARNING: RAID member! || echo Safe注意/dev/sdb是常见命名但实际可能是/dev/nvme0n1NVMe、/dev/mmcblk0eMMC、/dev/xvdaXen 虚拟机。务必用lsblk确认不要凭经验猜测。曾有同事在 AWS EC2 上误将/dev/xvda系统盘当成数据盘操作导致实例无法启动。第二步备份原始分区表强制# 备份 MBR512 字节和分区表前 512 字节 sudo dd if/dev/sdb of/tmp/sdb_mbr_backup.bin bs512 count1 # 备份整个磁盘前 1MB含 MBR 和可能的 bootcode sudo dd if/dev/sdb of/tmp/sdb_first_mb.bin bs1M count1 # 验证备份完整性MD5 应一致 md5sum /tmp/sdb_mbr_backup.bin sudo dd if/dev/sdb bs512 count1 2/dev/null | md5sum提示备份文件必须存到其他磁盘如/home/backup/绝不能存在/dev/sdb自身或其子分区上。我见过三次因备份存错位置操作失败后连恢复基础都做不到。第三步卸载所有关联分区# 列出该盘所有分区及挂载点 lsblk /dev/sdb -o NAME,MOUNTPOINT # 逐个卸载注意/dev/sdb1、/dev/sdb2 等 sudo umount /dev/sdb1 sudo umount /dev/sdb2 # 如果提示 “target is busy”用 lsof 查进程 sudo lsof D /mnt/data # 替换为实际挂载点 sudo fuser -v /mnt/data # 更直观显示占用进程 # 杀死进程谨慎 sudo fuser -k /mnt/data3.2 创建新分区主分区、扩展分区与逻辑分区的实操差异以一块 20GB 的新 SATA 盘/dev/sdb为例演示三种分区创建方式场景 1创建单个主分区最常用sudo fdisk /dev/sdb # 进入交互界面 Command (m for help): p # 先打印当前状态应为空 Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors Units: sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Command (m for help): n # 新建分区 Partition type p primary (default) e extended Select (default p): p # 选主分区 Partition number (1-4, default 1): 1 # 分区号 1 First sector (2048-41943039, default 2048): 2048 # 起始扇区1MB 对齐 Last sector, sectors or size{K,M,G,T,P} (2048-41943039, default 41943039): 10G # 结束位置10G # fdisk 自动计算10G 10×1024×1024×1024 / 512 20971520 扇区起始 2048 → 结束 20973567 Command (m for help): p # 再次查看 /dev/sdb1 2048 20973567 20971520 10G 83 Linux # 类型 83 Linux native Command (m for help): w # 写入并退出 The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks.实操心得10G输入比手动算扇区数安全得多。fdisk内部会按 512 字节扇区换算且自动向下取整到最近扇区避免越界错误。但要注意10G是“至少 10GB”实际分配可能略多因扇区对齐p命令显示的20971520扇区才是精确值。场景 2创建扩展分区 逻辑分区突破 4 分区限制sudo fdisk /dev/sdb Command (m for help): d # 先删掉刚建的 sdb1如果存在 Selected partition 1 Partition 1 has been deleted. Command (m for help): n Partition type p primary (default) e extended Select (default p): e # 选扩展分区 Partition number (1-4, default 1): 1 # 占用主分区槽位 1 First sector (2048-41943039, default 2048): 2048 Last sector, sectors or size{K,M,G,T,P} (2048-41943039, default 41943039): 15G # 扩展分区占 15G Command (m for help): n All primary partitions are in use. Adding logical partition 5 # 自动进入逻辑分区流程 First sector (31459328-41943039, default 31459328): # 起始自动设为扩展分区起始 Last sector, sectors or size{K,M,G,T,P} (31459328-41943039, default 41943039): 4G Command (m for help): p Device Boot Start End Sectors Size Id Type /dev/sdb1 2048 31459327 31457280 15G 5 Extended /dev/sdb5 4096 31459327 31455232 15G 83 Linux # 逻辑分区编号从 5 开始 # 注意sdb5 的 Start 是 4096不是 2048 —— 因为扩展分区内部有额外的 EBRExtended Boot Record结构 Command (m for help): w关键原理逻辑分区不是直接写在 MBR 里而是通过链式 EBR 实现。每个逻辑分区前有一个 512 字节的 EBR记录下一个逻辑分区位置。fdisk自动管理这个链你只需关心起始/结束扇区。但要知道逻辑分区的最小大小受 EBR 开销限制通常不能小于 1MB。场景 3创建 EFI 系统分区UEFI 启动必需sudo fdisk /dev/sdb Command (m for help): n Partition type p primary (default) e extended Select (default p): p Partition number (1-4, default 1): 1 First sector (2048-41943039, default 2048): 2048 Last sector, sectors or size{K,M,G,T,P} (2048-41943039, default 41943039): 512M Command (m for help): t # 修改分区类型 Selected partition 1 Hex code (type L to list all codes): L # 列出所有类型 ... ef EFI (FAT-12/16/32) ... Hex code (type L to list all codes): ef # 设为 EFI 类型 Command (m for help): p /dev/sdb1 2048 1050623 1048576 512M ef EFI System # 类型 ef Command (m for help): w注意事项EFI 分区必须格式化为 FAT32mkfs.fat -F32 /dev/sdb1且挂载到/boot/efi。类型代码ef是 UEFI 固件识别的关键设错则无法启动。3.3 编辑现有分区调整大小与修改类型调整分区大小仅支持扩展分区内的逻辑分区fdisk不能直接调整主分区大小如sdb1因为 MBR 分区表只存起始/结束扇区不存文件系统元数据。要扩容主分区必须用fdisk删除原分区d用n重建分区起始扇区必须与原分区完全相同否则数据丢失结束扇区设为更大值w写入后用resize2fs /dev/sdb1ext4或xfs_growfs /mount/pointXFS扩容文件系统但对逻辑分区如sdb5fdisk支持直接调整sudo fdisk /dev/sdb Command (m for help): p Device Boot Start End Sectors Size Id Type /dev/sdb1 2048 31459327 31457280 15G 5 Extended /dev/sdb5 4096 31459327 31455232 15G 83 Linux Command (m for help): d Partition number (1,5, default 5): 5 # 只删逻辑分区扩展分区 sdb1 保留 Command (m for help): n All primary partitions are in use. Adding logical partition 5 First sector (4096-31459327, default 4096): 4096 Last sector, sectors or size{K,M,G,T,P} (4096-31459327, default 31459327): 18G # 扩大到 18G Command (m for help): p # 查看新尺寸 /dev/sdb5 4096 37752831 37748736 18G 83 Linux Command (m for help): w # 之后运行sudo resize2fs /dev/sdb5修改分区类型关键系统标识sudo fdisk /dev/sdb Command (m for help): p Device Boot Start End Sectors Size Id Type /dev/sdb1 2048 1050623 1048576 512M 83 Linux Command (m for help): t # 修改类型 Selected partition 1 Hex code (type L to list all codes): L ... 82 Linux swap / Solaris 83 Linux 8e Linux LVM ... Hex code (type L to list all codes): 82 # 改为 swap Command (m for help): p /dev/sdb1 2048 1050623 1048576 512M 82 Linux swap / Solaris Command (m for help): w # 之后运行sudo mkswap /dev/sdb1 sudo swapon /dev/sdb1重要分区类型代码Id只是给操作系统看的标签不影响数据。但 swap、LVM、EFI 等类型内核和 initramfs 会据此自动启用对应功能。设错可能导致系统无法识别 swap 或启动失败。3.4 删除分区安全与彻底的两种方式方式 1交互式删除推荐用于单个分区sudo fdisk /dev/sdb Command (m for help): p Device Boot Start End Sectors Size Id Type /dev/sdb1 2048 1050623 1048576 512M 82 Linux swap / Solaris /dev/sdb2 1050624 31459327 30408704 14G 83 Linux Command (m for help): d Partition number (1,2, default 2): 1 # 删除 sdb1 Partition 1 has been deleted. Command (m for help): p # 确认已删 Device Boot Start End Sectors Size Id Type /dev/sdb2 1050624 31459327 30408704 14G 83 Linux Command (m for help): w # 写入方式 2清空整个磁盘分区表灾难恢复必备sudo fdisk /dev/sdb Command (m for help): o # 创建新的空 DOS 分区表覆盖 MBR Created a new DOS disklabel with disk identifier 0x12345678. Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks. # 此时 lsblk 显示 /dev/sdb 下无任何分区对比o命令比连续按d删除所有分区更快、更彻底。它直接重写 MBR 的 64 字节分区表为全 0而d只是把各条目设为 0。o后lsblk立刻清空dw后可能残留旧设备节点需partprobe刷新。3.5 显示分区信息fdisk -l 的深度解读fdisk -l是诊断核心命令但输出需逐行解读sudo fdisk -l /dev/sdb Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors Units: sectors of 1 * 512 512 bytes # 单位扇区 × 512 字节 Sector size (logical/physical): 512 bytes / 512 bytes # 硬件扇区大小 I/O size (minimum/optimal): 512 bytes / 512 bytes # 最小/最佳 IO 大小 Disklabel type: dos # 分区表类型dosMBR Disk identifier: 0x1a2b3c4d # MBR 磁盘标识符随机生成 Device Boot Start End Sectors Size Id Type /dev/sdb1 2048 1050623 1048576 512M 82 Linux swap / Solaris /dev/sdb2 1050624 31459327 30408704 14G 83 LinuxBoot 列*表示活动分区MBR 启动标志仅对主分区有效。逻辑分区永不显示*。Start/End/Sectors起始/结束扇区号Sectors是数量。计算大小(End - Start 1) × 512字节。Id 列十六进制类型码82swap83Linux8eLVMfdLinux RAID auto。Type 列fdisk根据 Id 码翻译的名称但不保证准确如83可能是 ext4/xfs/btrfsfdisk不识别文件系统。实战技巧当fdisk -l显示Disklabel type: unknown说明分区表损坏或非标准格式如某些加密盘。此时testdisk工具比fdisk更擅长修复。4. 高频问题与避坑指南那些官方文档不会告诉你的细节4.1 “fdisk -l 不显示新插入的 USB 盘”——设备扫描与缓存问题现象插上 USB 盘lsblk看不到/dev/sdcfdisk -l也无输出。排查步骤# 1. 检查内核是否识别到设备 dmesg | tail -20 | grep -i usb\|sd # 应看到类似[ 1234.567890] sd 2:0:0:0: [sdc] 3907029168 512-byte logical blocks # 2. 如果 dmesg 有识别但 /dev/sdc 不存在可能是 udev 规则延迟 sudo udevadm trigger --subsystem-matchblock sudo udevadm settle # 等待 udev 完成 # 3. 如果 dmesg 无识别检查 USB 供电或线缆尤其 USB 3.0 设备在 USB 2.0 插座上可能不识别经验在嵌入式 Linux如树莓派上USB 存储设备有时需要echo 1 /sys/bus/usb/drivers/usb-storage/bind手动绑定驱动。fdisk本身不负责设备发现它只操作已存在的/dev/xxx节点。4.2 “删除分区后 lsblk 仍显示旧分区”——内核分区缓存未刷新现象fdisk /dev/sdb→d→w后lsblk仍显示/dev/sdb1。根本原因Linux 内核维护分区缓存fdisk的w命令调用BLKRRPARTioctl 通知内核重读但某些情况下如设备忙、RAID 层干扰会失败。解决方案# 方案 1强制内核重读分区表最常用 sudo partprobe /dev/sdb # 方案 2如果 partprobe 无效尝试 kpartx针对 multipath 设备 sudo kpartx -d /dev/sdb # 删除映射 sudo kpartx -a /dev/sdb # 重新映射 # 方案 3终极手段——重启内核模块慎用 sudo modprobe -r sd_mod sudo modprobe sd_mod注意partprobe不会卸载已挂载分区它只刷新内核的分区表视图。如果分区仍在使用partprobe可能失败并提示 “device is busy”。4.3 “fdisk 创建的分区无法格式化Invalid argument”——对齐错误现象sudo mkfs.ext4 /dev/sdb1报错 “Invalid argument”。原因分析分区起始扇区未对齐到存储设备的最佳 IO 边界。现代 SSD/NVMe 要求 4KB 对齐8 个 512B 扇区而fdisk默认从 20481MB开始是安全的但如果手动输入1作为起始扇区就会出错。验证方法# 查看设备物理扇区大小和对齐偏移 sudo cat /sys/block/sdb/queue/logical_block_size # 应为 512 sudo cat /sys/block/sdb/queue/physical_block_size # 常为 4096 sudo cat /sys/block/sdb/alignment_offset # 应为 0表示对齐 # 计算分区起始是否对齐(Start × 512) % PhysicalBlockSize 0 # 如 Start2048 → 2048×5121048576 → 1048576 % 4096 0 ✓ # 如 Start1 → 1×512512 → 512 % 4096 512 ≠ 0 ✗修复用fdisk重新创建分区起始扇区务必用默认值2048或确保(Start × 512) % 4096 0。4.4 “主分区删除后扩展分区自动消失”——MBR 结构连锁反应现象fdisk /dev/sdb中先删sdb1主分区再删sdb2扩展分区p显示只剩sdb5逻辑分区但sdb2已不见。原理MBR 中扩展分区条目Id5指向一个 EBR 扇区该 EBR 包含逻辑分区链表。当sdb2扩展分区被删除MBR 中该条目清零内核不再识别扩展分区结构sdb5变成“孤儿分区”lsblk可能不显示它。恢复方法# 1. 用 testdisk 扫描恢复最可靠 sudo testdisk /dev/sdb # 选择 “Proceed” → “Intel” → “Analyse” → “Quick Search” → 找到 sdb2 和 sdb5 → “Write” # 2. 手动重建需知道原 sdb2 起始扇区 sudo fdisk /dev/sdb Command (m for help): n Partition type: e First sector: [原 sdb2 Start] Last sector: [原 sdb2 End] Command (m for help): w # 然后用 fdisk 进入用 n 重建 sdb5教训删除扩展分区前务必先记下其 Start/End 扇区p命令输出或用sfdisk -d /dev/sdb backup.txt备份完整分区表。4.5 “fdisk 在 LVM 物理卷上操作失败”——LVM 元数据冲突现象对 LVM PV如/dev/sdb执行fdisk提示 “Device contains LVM2_member signature” 并拒绝操作。原因LVM 在设备开头写入了元数据签名LVM2 001fdisk检测到后出于安全考虑阻止写入。正确做法# 方案 1先移除 LVM 签名如果确定不再用 LVM sudo pvremove /dev/sdb # 方案 2用 LVM 命令管理推荐 sudo pvdisplay /dev/sdb # 查看 PV 信息 sudo vgremove vg_name # 删除卷组 sudo pvremove /dev/sdb # 清除 PV 签名 # 方案 3强制 fdisk不推荐可能破坏 LVM sudo fdisk -c /dev/sdb # -c 关闭 DOS
上一篇/下一篇内容由系统自动关联
返回资讯列表 →