Linux下SD卡分区实战:从fdisk到parted的完整指南
1. 项目概述:为什么要在Linux下分区SD卡?
如果你手头有一张SD卡,无论是准备给树莓派做系统盘,还是想把它格式化成多个分区来分别存放数据和备份,在Linux系统下操作都是一个高效且透明的选择。与Windows下依赖图形化工具不同,Linux的命令行工具提供了更精细的控制权,你能清楚地知道每一个操作步骤背后的原理,这对于嵌入式开发、服务器维护或者仅仅是学习Linux系统管理来说,都是非常宝贵的实践经验。我遇到过很多新手,面对fdisk、parted这些命令感到畏惧,但其实一旦理解了磁盘、分区、文件系统这几个核心概念,整个过程就像搭积木一样清晰。今天,我就以一张32GB的SD卡为例,带你走一遍从识别设备到完成分区的完整流程,并分享一些我踩过坑才总结出来的实操技巧。
2. 核心概念与工具选型解析
在动手之前,我们必须搞清楚几个关键概念,这能帮你理解每一步在做什么,而不是机械地输入命令。
2.1 磁盘、分区与文件系统:它们是什么关系?
你可以把整张SD卡想象成一块空地(物理磁盘)。直接在这块空地上盖房子(存放文件)是不现实的,因为太混乱了。我们首先需要在这块空地上划分出几个有明确边界的小区(分区)。最后,在每个小区里,我们还要建立一套管理规则,比如道路怎么修、门牌号怎么编,这套规则就是文件系统(如ext4, FAT32, NTFS)。所以,流程是:物理磁盘 -> 创建分区 -> 在分区上创建文件系统。
在Linux中,一切皆文件,磁盘设备也不例外。你的SD卡插入后,通常会被识别为/dev/sdX(如sdb,sdc)或/dev/mmcblkX(如mmcblk0)。如何区分?简单来说,通过USB读卡器连接的SD卡通常是/dev/sdX格式,而直接插入笔记本SD卡槽或某些嵌入式板载卡槽的,可能是/dev/mmcblkX格式。这是第一个容易混淆的点。
2.2 分区表类型:MBR vs. GPT
在划分小区(分区)之前,我们还需要一张总规划图,这张图就是分区表。它记录了分区的数量、大小和起始位置。主要有两种:
- MBR (Master Boot Record):传统格式,历史悠久,兼容性极好。但有两个主要限制:最多只支持4个主分区(可以通过扩展分区和逻辑分区绕开,但稍复杂);单个分区最大支持2TB。
- GPT (GUID Partition Table):现代格式,是UEFI启动的标配。它没有分区数量限制(实际操作系统会有限制),支持远超2TB的磁盘容量,并且自带备份,更安全可靠。
对于SD卡,如果你的用途是:
- 树莓派(旧版):通常使用MBR,因为其Bootloader可能只认MBR。
- 通用数据存储或现代UEFI设备:优先选择GPT。
- 容量小于2TB:两者皆可,但GPT是未来趋势。
2.3 工具选择:fdisk vs. parted
Linux下最常用的两个分区工具是fdisk和parted。
fdisk:经典、交互式命令行工具。它简单直观,通过问答式菜单进行操作,非常适合初学者理解分区过程。但它对GPT的支持是后来加入的,在某些老版本系统中可能不是默认选项(需要使用gdisk命令处理GPT)。parted:更强大、支持非交互式(脚本化)操作的工具。它从一开始就原生支持MBR和GPT,并且能处理更多高级功能(如调整已有分区大小)。它的命令语法更直接,但学习曲线稍陡。
我的建议是:如果你是第一次操作,从fdisk开始,它能帮你建立清晰的概念。当你需要批量操作或处理复杂分区时,再转向parted。本文将以fdisk(针对GPT分区表)和parted两种方式分别演示。
重要警告:分区操作会永久性擦除磁盘上的数据!请务必在操作前,通过
lsblk或fdisk -l命令反复确认你操作的是正确的设备(比如/dev/sdb),而不是你的系统盘(通常是/dev/sda)。误操作会导致数据丢失,无法轻易恢复。
3. 完整实操流程:从识别到挂载
现在,我们进入实战环节。请准备好你的SD卡和Linux环境(可以是实体机、虚拟机,或者通过SSH连接的远程服务器)。
3.1 第一步:准确识别SD卡设备
插入SD卡后,打开终端。我们需要找到系统分配给SD卡的设备名。
方法A:使用lsblk命令(推荐)
lsblk这个命令会以树状图列出所有块设备(磁盘和分区)。输出类似:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 465.8G 0 disk ├─sda1 8:1 0 512M 0 part /boot/efi ├─sda2 8:2 0 732M 0 part /boot └─sda3 8:3 0 464.6G 0 part / sdb 8:16 1 29.7G 0 disk这里,sda是我的系统硬盘,下面有三个分区。sdb就是我刚插入的、29.7G的SD卡,它目前还没有任何分区(下面没有├─或└─开头的行)。RM列为1表示是可移动设备,这也能辅助判断。
方法B:使用fdisk -l命令(需要sudo权限)
sudo fdisk -l这个命令会列出所有磁盘的详细信息。你需要在一堆输出中找到你的SD卡,通常是通过容量来判断。例如:
Disk /dev/sdb: 29.7 GiB, 31914983424 bytes, 62333952 sectors Disk model: USB3.0 CRW -SD 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这里明确指出了设备是/dev/sdb,容量29.7GiB,并且当前的分区表类型是dos(即MBR)。
记录下你的SD卡设备名,假设为/dev/sdb。接下来的所有操作都将基于这个设备名,请务必根据你的实际情况替换!
3.2 第二步:卸载已挂载的分区(如果存在)
如果这张SD卡之前被使用过,并且系统自动挂载了它的分区(比如在文件管理器里打开了),我们必须先卸载它,否则分区工具无法修改它。
# 首先,检查SD卡是否有分区被挂载 lsblk /dev/sdb # 如果看到类似 sdb1 后面有 MOUNTPOINT,比如 /media/username/XXX,就需要卸载 # 卸载分区,将 sdb1 替换为你的实际分区名 sudo umount /dev/sdb1 # 如果有多个分区,如 sdb2, sdb3,也需要逐一卸载 sudo umount /dev/sdb2确保所有相关分区都卸载成功后,再进行下一步。
3.3 第三步:使用fdisk创建GPT分区(方案一)
假设我们打算将这张32GB的SD卡分成两个区:一个16GB的ext4分区用于Linux数据,一个16GB的FAT32分区用于跨平台共享。
启动fdisk并指定设备:
sudo fdisk /dev/sdb你会进入fdisk的交互式命令行,提示符变为
Command (m for help):。创建新的GPT分区表(这会清除所有现有数据): 输入
g然后按回车。这会创建一个新的GPT磁盘标签(分区表)。终端会提示:Created a new GPT disklabel (GUID: ...)。创建第一个分区(16GB, ext4):
- 输入
n创建新分区。 - 分区号直接按回车接受默认值(1)。
- 第一个扇区直接按回车接受默认值(通常是2048,为对齐留出空间)。
- 设置分区大小:输入
+16G然后回车。这表示分区从起始位置向后延伸16GB。 - 此时第一个分区创建完成。默认分区类型是“Linux filesystem”,这正合我们意(对应ext4)。
- 输入
创建第二个分区(剩余空间, FAT32):
- 再次输入
n创建第二个分区。 - 分区号、起始扇区都直接按回车接受默认值(它会自动接在上一个分区之后)。
- 结束扇区直接按回车,表示使用所有剩余空间。
- 现在,我们需要更改这个分区的类型。输入
t然后回车。 - 选择分区号
2。 - 输入分区类型代码
L来列出所有已知类型代码。 - 在列表中寻找“Microsoft basic data”或“W95 FAT32 (LBA)”,其代码通常是
b或c。我们输入c(对应W95 FAT32 LBA)。 - 终端会提示:
Changed type of partition 'Linux filesystem' to 'W95 FAT32 (LBA)'。
- 再次输入
检查分区布局: 输入
p打印当前的分区表,检查一下是否和你预期的一致。应该能看到两个分区,sdb1和sdb2,大小和类型正确。将更改写入磁盘(关键一步): 确认无误后,输入
w然后回车,将分区表写入磁盘并退出fdisk。这是一个不可逆的操作!如果发现错了,可以输入q不保存退出。
3.4 第四步:使用parted创建分区(方案二)
如果你更喜欢parted的直接,或者需要脚本化,可以这样做:
启动parted:
sudo parted /dev/sdb创建GPT分区表:
mklabel gpt输入
yes确认。创建第一个分区:
mkpart primary ext4 1MiB 16GiBprimary是分区类型(主分区)。ext4是文件系统类型(parted会记录这个信息,但实际格式化仍需单独进行)。1MiB 16GiB是分区的起始和结束位置。这里强烈建议使用MiB/GiB为单位并从1MiB开始,这能保证分区的最佳性能(对齐)。
创建第二个分区:
mkpart primary fat32 16GiB 100%100%表示用到磁盘末尾。查看与退出:
print # 查看分区表 quit # 退出parted
3.5 第五步:在分区上创建文件系统(格式化)
分区只是划好了地盘,现在要给每个地盘建立管理规则(文件系统)。我们需要针对每个分区单独操作。
格式化第一个分区为ext4:
sudo mkfs.ext4 /dev/sdb1命令会执行,输出一些信息,最后显示
Writing superblocks and filesystem accounting information完成。格式化第二个分区为FAT32:
sudo mkfs.vfat -F 32 /dev/sdb2-F 32参数指定了FAT32格式。对于大于32GB的分区,Windows的format命令可能不允许用FAT32,但Linux的mkfs.vfat通常可以,不过出于兼容性考虑,大分区更推荐exFAT(sudo mkfs.exfat /dev/sdb2)。
3.6 第六步:挂载并使用新分区
格式化后,分区就可以使用了。你可以手动挂载到任意目录。
# 创建两个挂载点目录 sudo mkdir -p /mnt/data_ext4 sudo mkdir -p /mnt/data_fat32 # 挂载分区 sudo mount /dev/sdb1 /mnt/data_ext4 sudo mount /dev/sdb2 /mnt/data_fat32 # 检查挂载结果 df -h /dev/sdb1 /dev/sdb2现在,你就可以通过/mnt/data_ext4和/mnt/data_fat32这两个目录来访问SD卡上的两个分区了。向里面复制文件试试吧。
想让SD卡插入时自动挂载?这需要修改/etc/fstab文件,但考虑到SD卡可能在不同机器间插拔,自动挂载配置容易因设备名(/dev/sdb可能变成/dev/sdc)变化而出错。更现代的方案是使用文件系统的UUID或LABEL来标识分区,但这属于进阶内容,初期建议手动挂载更安全。
4. 高级技巧与深度解析
掌握了基本流程后,我们来看看一些能提升效率、避免问题的进阶知识。
4.1 分区对齐:为什么从1MiB开始?
在之前parted的示例中,我特意让分区从1MiB开始,而不是0扇区或1扇区。这叫做分区对齐。现代存储设备(SSD、SD卡、高级格式硬盘)的物理扇区大小通常是4KB(4096字节)。如果分区的起始位置不是4KB的整数倍,那么一个文件系统逻辑块(比如4KB)可能会跨越两个物理扇区。当读写这个块时,设备就需要进行两次操作,严重降低性能,这种现象称为“读写放大”。
从1MiB(1048576字节,正好是4096的整数倍)开始,可以确保分区与绝大多数存储设备的物理结构对齐,从而获得最佳性能。fdisk的新版本在创建GPT分区时,默认起始扇区就是2048(2048扇区 * 512字节/扇区 = 1MiB),已经帮我们做了对齐。
4.2 使用UUID或LABEL挂载的稳定性
在/etc/fstab中,用/dev/sdb1这样的设备名来挂载是非常不可靠的,因为设备名(sda,sdb,sdc)取决于系统检测到设备的顺序。今天你的SD卡是sdb,明天插了个U盘可能就变成sdc了。
更稳定的方法是使用UUID(全局唯一标识符)或LABEL(卷标)。
查看分区的UUID和LABEL:
sudo blkid /dev/sdb1 /dev/sdb2输出类似:
/dev/sdb1: UUID="a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8" TYPE="ext4" /dev/sdb2: UUID="1234-ABCD" TYPE="vfat"在格式化时指定LABEL(可选但推荐):
sudo mkfs.ext4 -L "MyLinuxData" /dev/sdb1 sudo mkfs.vfat -F 32 -n "MySharedData" /dev/sdb2之后在
/etc/fstab中就可以这样写:UUID=a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8 /mnt/data_ext4 ext4 defaults 0 2 LABEL=MySharedData /mnt/data_fat32 vfat defaults,uid=1000,gid=1000,umask=022 0 0这样,无论设备名怎么变,系统都能准确找到并挂载正确的分区。
4.3 处理已分配全盘空间的分区表
有时候,你可能会遇到一种情况:SD卡显示有一个分区占用了全部容量(比如/dev/sdb1),但你用fdisk删除这个分区并创建新分区表时,可能会失败或报错。这通常是因为旧的分区信息还被内核缓存着。
解决方法:使用wipefs命令清除设备上的所有文件系统签名和分区表信息,然后让内核重新读取。
# 谨慎操作!确认/dev/sdb是你的SD卡 sudo wipefs -a /dev/sdb # 然后通知内核重新读取分区表 sudo partprobe /dev/sdb # 或者更彻底地,可以断开再重新连接SD卡硬件执行完wipefs后,设备在lsblk里会显示为一个没有任何分区的纯净磁盘,此时再使用fdisk或parted进行操作就会非常顺利。
5. 常见问题与排查技巧实录
即使按照步骤操作,也可能会遇到各种问题。这里记录了几个我亲身经历过的“坑”及其解决办法。
5.1 问题:fdisk中看不到新建的分区,或者lsblk不显示
- 现象:在
fdisk里用w命令保存退出后,立刻用lsblk查看,发现分区(如sdb1)没有出现。 - 原因:内核没有及时更新内存中的分区表信息。
- 解决:运行
sudo partprobe /dev/sdb命令通知内核重新读取/dev/sdb的分区表。如果还不行,最彻底的方法是物理上重新拔插一次SD卡,或者使用sudo udevadm trigger。
5.2 问题:无法格式化,提示“Device or resource busy”
- 现象:运行
mkfs命令时,报错/dev/sdb1 is apparently in use by the system; will not make a filesystem here!。 - 原因:该分区正在被系统使用,最常见的原因就是它被自动挂载了(比如桌面环境文件管理器的自动挂载功能)。
- 解决:
- 使用
lsblk或mount | grep sdb1确认分区是否被挂载。 - 使用
sudo umount /dev/sdb1卸载它。 - 如果卸载失败,检查是否有终端窗口的当前工作目录(
pwd)正在该分区下,或者是否有程序正在访问该分区内的文件。关闭这些程序或切换到其他目录。
- 使用
5.3 问题:Windows无法识别Linux创建的分区
- 现象:在Linux下分好区并格式化的SD卡,插到Windows电脑上,只显示其中一个分区(通常是FAT32那个),或者提示需要格式化。
- 原因:
- 文件系统不支持:Windows默认不支持ext2/3/4文件系统。所以ext4分区在Windows下不可见是正常的。
- 分区表问题:如果你创建的是GPT分区表,而你的Windows系统是较旧的Legacy BIOS模式,可能无法正确识别。
- “隐藏”的ESP/MSR分区:如果你不小心创建了EFI系统分区(ESP)或Microsoft保留分区(MSR),Windows可能会表现出奇怪的行为。
- 解决:
- 对于需要在Windows和Linux间共享的数据,请使用FAT32、exFAT或NTFS分区。
- 确保SD卡的分区表类型(MBR/GPT)与目标设备兼容。对于最大兼容性,老设备用MBR。
- 在Linux下用
sudo fdisk -l /dev/sdb仔细检查分区类型。确保数据分区的类型是“Microsoft basic data”(代码0700in MBR 或EBD0A0A2-B9E5-4433-87C0-68B6B72699C7in GPT)。
5.4 问题:分区后容量“缩水”了
- 现象:一张标称32GB的SD卡,分区格式化后,在文件管理器里显示只有29.7GB左右可用。
- 原因:这是完全正常的,并非操作错误。厂商的“GB”是十进制(1GB = 10^9 bytes),而操作系统的“GiB”是二进制(1GiB = 2^30 bytes)。32,000,000,000 bytes ≈ 29.8 GiB。此外,文件系统本身(如ext4的inode表、日志区)和分区表也会占用少量空间。
- 解决:无需解决,这是预期行为。你可以通过
df -h和sudo fdisk -l对比查看,总容量基本是匹配的。
5.5 快速问题排查清单
| 问题现象 | 可能原因 | 排查命令/步骤 |
|---|---|---|
找不到/dev/sdb设备 | SD卡未识别、接触不良、读卡器故障 | dmesg | tail查看内核日志;重新插拔;换读卡器或接口 |
fdisk命令报错或无响应 | 设备被锁定、有进程占用 | sudo lsof | grep /dev/sdb查看占用进程;sudo umount卸载所有分区 |
| 格式化速度极慢或报I/O错误 | SD卡物理损坏、寿命将至 | sudo badblocks -sv /dev/sdb检测坏块(慎用,会写数据) |
| 写入文件时提示“只读文件系统” | 文件系统损坏、SD卡写保护开关打开 | 检查SD卡侧面的物理锁;尝试sudo fsck /dev/sdb1修复文件系统 |
最后,分享一个我自己的习惯:在对任何存储设备进行分区操作前,如果里面有重要数据,我一定会先用dd或rsync做一次完整的磁盘或文件备份。命令看起来复杂,但dd if=/dev/sdb of=~/sd_card_backup.img bs=4M status=progress这一行命令,可能在某天会救你于水火。分区有风险,操作需谨慎,但一旦掌握了原理和工具,你就能完全掌控这些存储介质,让它们在你的项目中发挥最大效用。
