1. 为什么需要U盘挂载到开发板
在嵌入式开发过程中,我们经常需要在开发板和主机之间传输文件。虽然可以通过网络传输(如SSH、FTP)或者串口工具来实现,但这些方法要么依赖网络环境,要么传输速度较慢。相比之下,使用U盘进行文件传输有几个显著优势:
- 传输速度更快(USB2.0理论速度可达480Mbps,实际传输速度通常在20-40MB/s)
- 不受网络环境限制
- 操作简单直观
- 适合大文件传输
我在实际项目中发现,当需要传输几十MB甚至上百MB的固件或镜像文件时,U盘挂载是最可靠的选择。特别是在现场调试时,网络环境可能不稳定,U盘就成了救命稻草。
2. 准备工作:硬件与软件需求
2.1 硬件准备
首先确认你的开发板支持USB Host功能。常见的开发板如树莓派、NanoPi、Orange Pi等都带有USB接口。你需要准备:
- 开发板(已安装Linux系统)
- U盘(建议使用FAT32格式,兼容性最好)
- USB数据线(如果需要额外供电)
注意:有些低功耗开发板可能无法为U盘提供足够电力,这时需要使用带外接电源的USB Hub。
2.2 软件准备
开发板的Linux系统需要包含以下内核模块:
- USB存储驱动(通常是usb-storage)
- 文件系统驱动(如vfat、ext4等,取决于U盘格式)
- 自动挂载工具(可选,如udisks2)
可以通过以下命令检查内核是否支持:
bash复制lsmod | grep usb_storage
lsmod | grep vfat
如果没有输出,可能需要重新编译内核,勾选相关选项:
code复制Device Drivers -> USB support -> USB Mass Storage support
File systems -> DOS/FAT/NT Filesystems -> VFAT (Windows-95) fs support
3. 手动挂载U盘详细步骤
3.1 识别U盘设备
插入U盘后,首先需要确认系统是否识别到了设备。使用dmesg查看内核日志:
bash复制dmesg | tail
你应该能看到类似这样的输出:
code复制[ 1234.567890] usb 1-1: new high-speed USB device number 2 using ehci-platform
[ 1234.789012] usb-storage 1-1:1.0: USB Mass Storage device detected
[ 1235.123456] scsi host0: usb-storage 1-1:1.0
[ 1236.234567] sd 0:0:0:0: [sda] 15633408 512-byte logical blocks: (8.00 GB/7.45 GiB)
[ 1236.345678] sd 0:0:0:0: [sda] Write Protect is off
[ 1236.456789] sd 0:0:0:0: [sda] Mode Sense: 23 00 00 00
[ 1236.567890] sd 0:0:0:0: [sda] No Caching mode page found
[ 1236.678901] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 1236.789012] sda: sda1
[ 1237.123456] sd 0:0:0:0: [sda] Attached SCSI removable disk
关键信息是sda1,表示系统识别到了U盘,并且第一个分区是sda1。
3.2 创建挂载点
在开发板上创建一个目录作为挂载点:
bash复制mkdir -p /mnt/usb
建议使用/mnt目录,这是Linux系统中传统的挂载点目录。
3.3 挂载U盘
现在可以挂载U盘了。假设U盘是FAT32格式:
bash复制mount -t vfat /dev/sda1 /mnt/usb -o rw,umask=000
参数说明:
-t vfat:指定文件系统类型/dev/sda1:U盘设备节点/mnt/usb:挂载点-o rw,umask=000:挂载为可读写,权限设置为777
如果U盘是NTFS格式,需要先安装ntfs-3g:
bash复制apt-get install ntfs-3g # Debian/Ubuntu
mount -t ntfs-3g /dev/sda1 /mnt/usb
3.4 验证挂载
使用mount命令查看挂载情况:
bash复制mount | grep usb
应该能看到类似输出:
code复制/dev/sda1 on /mnt/usb type vfat (rw,relatime,fmask=0000,dmask=0000,allow_utime=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
也可以直接查看挂载点内容:
bash复制ls -l /mnt/usb
4. 自动挂载配置方法
手动挂载每次都需要输入命令,我们可以配置系统在U盘插入时自动挂载。
4.1 使用udev规则
创建udev规则文件:
bash复制vi /etc/udev/rules.d/99-usb-storage.rules
添加以下内容:
code复制ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /mnt/usb-%k", RUN+="/bin/mount -o rw,umask=000 /dev/%k /mnt/usb-%k"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /mnt/usb-%k", RUN+="/bin/rmdir /mnt/usb-%k"
保存后重新加载udev规则:
bash复制udevadm control --reload-rules
这样每次插入U盘时,系统会自动创建挂载点并挂载,命名格式为/mnt/usb-sda1。
4.2 使用autofs
另一种方法是使用autofs:
bash复制apt-get install autofs
编辑配置文件:
bash复制vi /etc/auto.master
添加:
code复制/mnt/usb /etc/auto.usb --timeout=30
创建auto.usb文件:
bash复制vi /etc/auto.usb
内容为:
code复制* -fstype=vfat,rw,umask=000 :/dev/&
重启autofs服务:
bash复制service autofs restart
现在访问/mnt/usb/sda1时会自动挂载,30秒不活动后自动卸载。
5. 文件传输实践技巧
5.1 传输大文件
使用rsync可以更可靠地传输大文件:
bash复制rsync -avzP /path/to/local/file /mnt/usb/
参数说明:
-a:归档模式-v:详细输出-z:压缩传输-P:显示进度和断点续传
5.2 保持文件权限
如果需要保留文件权限和属性,可以使用tar:
bash复制# 打包传输
tar cvf - /path/to/files | tar xvf - -C /mnt/usb
# 解包恢复
tar xvf /mnt/usb/backup.tar -C /target/directory
5.3 性能优化
对于大量小文件传输,可以先打包再传输。我在实际项目中测试过:
- 直接传输1000个1KB文件:耗时约45秒
- 打包后传输:耗时约3秒
6. 常见问题与解决方案
6.1 U盘无法识别
现象:插入U盘后dmesg没有相关输出
排查步骤:
- 检查USB接口是否正常
- 尝试不同的U盘
- 检查内核配置是否有USB存储支持
- 查看电源是否充足
6.2 挂载失败
错误信息:mount: wrong fs type, bad option, bad superblock...
解决方案:
- 确认文件系统类型:
sudo fdisk -l /dev/sda - 尝试不同文件系统类型:
mount -t auto /dev/sda1 /mnt/usb - 修复文件系统:
fsck /dev/sda1
6.3 只读文件系统
现象:无法创建或修改文件
解决方法:
- 检查挂载选项是否有rw
- 检查U盘是否写保护
- 尝试重新挂载:
mount -o remount,rw /mnt/usb
6.4 中文文件名乱码
解决方案:
挂载时指定编码:
bash复制mount -t vfat /dev/sda1 /mnt/usb -o rw,iocharset=utf8
如果仍然有问题,可以尝试:
bash复制mount -t vfat /dev/sda1 /mnt/usb -o rw,iocharset=gb2312
7. 安全卸载U盘
在拔出U盘前,务必先卸载:
bash复制umount /mnt/usb
或者使用更安全的命令:
bash复制sync && umount /mnt/usb
sync命令确保所有缓存数据写入磁盘。
重要提示:直接拔出U盘可能导致数据损坏,特别是当传输大文件时。我有一次没有卸载就直接拔U盘,导致整个文件系统损坏,最后不得不重新格式化。
8. 高级应用:通过U盘更新系统
在嵌入式系统中,U盘还可以用于系统升级。这里分享一个实际项目中的方案:
- 在U盘根目录创建
upgrade目录 - 将升级文件(如
update.tar.gz)放入该目录 - 开发板启动时检查该目录并自动升级
实现脚本示例:
bash复制#!/bin/bash
UPGRADE_DIR="/mnt/usb/upgrade"
UPDATE_FILE="$UPGRADE_DIR/update.tar.gz"
if [ -f "$UPDATE_FILE" ]; then
echo "Found update package, start upgrading..."
tar xzf "$UPDATE_FILE" -C /
rm -f "$UPDATE_FILE"
sync
echo "Upgrade completed, please reboot"
fi
可以将此脚本加入rc.local实现开机自动检查升级。
9. 性能测试与比较
为了帮助选择最佳传输方式,我做了以下测试(使用16GB USB2.0 U盘,FAT32格式):
| 传输方式 | 100MB文件耗时 | 1000个小文件耗时 |
|---|---|---|
| 直接cp | 4.2s | 28.5s |
| rsync | 4.5s | 26.8s |
| tar+cp | 3.8s | 5.2s |
| scp | 12.7s | 45.3s |
从测试结果可以看出,对于大文件,各种方式差异不大;但对于大量小文件,先打包再传输效率最高。
10. 替代方案评估
虽然U盘挂载很方便,但在某些场景下可能有更好的选择:
-
网络传输(NFS):适合频繁交换文件的开发环境
- 优点:无需插拔,实时同步
- 缺点:依赖网络
-
TF卡:如果开发板有TF卡槽
- 优点:更稳定,不易松动
- 缺点:传输速度可能较慢
-
USB网络共享:通过USB建立网络连接
- 优点:兼顾速度和稳定性
- 缺点:配置复杂
在实际项目中,我通常会同时配置多种方式,根据具体情况选择最合适的。例如日常开发用NFS,现场调试用U盘,量产烧录用TF卡。