1. 项目概述
作为一名嵌入式Linux开发者,我深知传统U盘拷贝方式的低效与痛苦。每次修改代码后都要经历"编译-拷贝-插拔-运行"的繁琐流程,严重拖慢了开发效率。经过多次实践,我总结出一套基于NFS的嵌入式开发环境搭建方案,通过一根网线实现Windows主机、Ubuntu虚拟机与I.MX6ULL开发板的三方直连,彻底告别U盘搬运时代。
这套方案的核心优势在于:
- 物理直连:仅需一根网线和USB网卡,无需路由器等额外设备
- 实时同步:通过NFS实现文件系统共享,代码修改即时生效
- 跨平台编译:在Ubuntu中交叉编译,直接在开发板运行
- 成本低廉:使用常见硬件设备,无需购买专业调试工具
2. 硬件准备与网络拓扑
2.1 硬件清单与连接
必需设备:
- Windows主机(本文以Win10为例)
- 安装VMware Workstation Pro
- Ubuntu虚拟机(推荐18.04 LTS及以上版本)
- I.MX6ULL开发板(本文使用正点原子型号)
- USB转网卡(推荐Realtek芯片)
- 标准网线(直连或交叉线均可,现代网卡大多支持自动翻转)
连接方案:
- 将USB网卡插入Windows主机的一个固定USB接口(重要!后续开发都使用同一接口)
- 网线一端连接USB网卡,另一端连接开发板ENET2接口(标注为eth0)
- 开发板通过串口线连接Windows,用于终端控制
注意:选择固定的USB接口是为了避免Windows重新识别网卡导致网络配置丢失。我在实践中发现,更换USB口会导致系统将其识别为新设备,需要重新配置网络参数。
2.2 IP地址规划
由于没有DHCP服务器,我们需要手动配置静态IP。建议采用以下方案:
| 设备 | IP地址 | 子网掩码 | 说明 |
|---|---|---|---|
| Windows USB网卡 | 192.168.5.10 | 255.255.255.0 | 宿主机直连网卡 |
| Ubuntu桥接网卡 | 192.168.5.11 | 255.255.255.0 | 与开发板通信的专用网卡 |
| 开发板eth0 | 192.168.5.12 | 255.255.255.0 | 目标设备 |
这个方案将三设备置于同一局域网段(192.168.5.0/24),同时避开了常见家用路由器网段(如192.168.1.x),减少冲突可能。
3. Windows端配置详解
3.1 USB网卡驱动安装
大多数USB网卡即插即用,但为确保最佳性能,建议:
- 访问设备制造商官网下载最新驱动
- 在设备管理器中检查网卡状态,确保无黄色感叹号
- 记录网卡名称(如"Realtek USB FE Family Controller")
3.2 静态IP配置步骤
- 插入USB网卡,当VMware提示时选择"连接到主机(Windows)"
- Win+R打开运行,输入
ncpa.cpl回车,打开网络连接 - 右键USB网卡 → 属性 → Internet协议版本4(TCP/IPv4)
- 按如下配置:
- IP地址:192.168.5.10
- 子网掩码:255.255.255.0
- 默认网关:留空
- DNS服务器:留空
重要提示:默认网关和DNS必须留空,否则会导致Windows主机的WiFi外网连接失效。我曾因此浪费两小时排查网络故障。
- 点击"确定"保存,无需重启
验证配置:
bash复制ping 192.168.5.10
应能收到来自本机的回复。
4. VMware虚拟机配置
4.1 桥接模式设置
- 关闭Ubuntu虚拟机
- 打开VMware → 编辑 → 虚拟网络编辑器
- 点击"更改设置"获取管理员权限
- 选择VMnet0(桥接模式)
- 在"已桥接到"下拉菜单中,手动选择你的USB网卡(非自动)
- 点击确定保存
4.2 双网卡配置策略
为实现Ubuntu同时访问外网和开发板,需要配置双网卡:
| 网卡类型 | 模式 | 用途 | 备注 |
|---|---|---|---|
| 网卡1 | NAT | 访问互联网 | 用于软件安装和更新 |
| 网卡2 | 桥接 | 连接开发板 | 桥接到USB网卡 |
配置步骤:
- 右键虚拟机 → 设置 → 添加 → 网络适配器
- 将新适配器设置为"自定义:VMnet0(桥接)"
- 确保原适配器保持NAT模式
- 启动Ubuntu虚拟机
5. Ubuntu网络配置
5.1 识别新增网卡
在终端执行:
bash复制ip a
查找没有IPv4地址的新网卡(通常为ens37或ens38)。记录其名称。
5.2 配置静态IP
临时设置(重启失效):
bash复制sudo ifconfig ens37 192.168.5.11 netmask 255.255.255.0 up
永久设置(推荐):
- 编辑网络配置文件:
bash复制sudo vi /etc/netplan/01-netcfg.yaml
- 添加以下内容(根据实际网卡名调整):
yaml复制network:
version: 2
renderer: networkd
ethernets:
ens33:
dhcp4: yes
ens37:
addresses: [192.168.5.11/24]
dhcp4: no
optional: yes
- 应用配置:
bash复制sudo netplan apply
6. 开发板网络配置
通过串口终端连接开发板,执行:
bash复制ifconfig eth0 192.168.5.12 netmask 255.255.255.0 up
测试连通性:
bash复制ping 192.168.5.11
应看到来自Ubuntu的回复,丢包率为0%。
7. NFS服务配置
7.1 Ubuntu端安装与配置
- 安装NFS服务:
bash复制sudo apt-get install nfs-kernel-server rpcbind
- 创建共享目录:
bash复制mkdir -p ~/linux/nfs
chmod 777 ~/linux/nfs
- 编辑exports文件:
bash复制sudo vi /etc/exports
添加:
code复制/home/yourname/linux/nfs *(rw,sync,no_root_squash)
- 重启服务:
bash复制sudo systemctl restart nfs-kernel-server
7.2 开发板挂载NFS
在开发板终端执行:
bash复制mount -t nfs -o nolock,nfsvers=3 192.168.5.11:/home/yourname/linux/nfs /mnt
验证挂载:
bash复制ls /mnt
应能看到共享目录内容。
8. 开发工作流实践
8.1 交叉编译环境配置
- 安装工具链:
bash复制sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
- 编写测试程序main.cpp:
cpp复制#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1,2,3,4,5};
for(auto& v : vec) {
std::cout << "Value: " << v << std::endl;
}
return 0;
}
- 交叉编译:
bash复制arm-linux-gnueabihf-g++ -std=c++11 -march=armv7-a -mfpu=neon main.cpp -o main
- 部署到NFS目录:
bash复制cp main ~/linux/nfs/
8.2 开发板运行测试
在开发板终端:
bash复制cd /mnt
./main
应看到程序输出。
9. 常见问题与解决方案
9.1 网络不通排查步骤
-
检查物理连接:
- 网线是否插紧
- USB网卡指示灯是否亮起
-
检查IP配置:
- Windows:ipconfig
- Ubuntu:ip a
- 开发板:ifconfig
-
测试连通性:
- 从开发板ping Ubuntu
- 从Ubuntuping开发板
- 从Windows ping两端
9.2 NFS挂载失败处理
- 检查服务状态:
bash复制sudo systemctl status nfs-kernel-server
- 查看共享权限:
bash复制sudo exportfs -v
- 尝试指定NFS版本:
bash复制mount -t nfs -o nolock,nfsvers=3 192.168.5.11:/path /mnt
9.3 开发板重启后配置丢失
由于ifconfig配置是临时的,建议:
- 将网络配置写入开发板启动脚本
- 或创建简单的shell脚本保存常用命令
- 在~/.bashrc中添加别名简化操作
10. 效率优化技巧
-
VS Code远程开发:
- 安装Remote-SSH插件
- 直接编辑Ubuntu上的代码文件
-
自动化脚本:
创建build-and-deploy.sh:bash复制#!/bin/bash arm-linux-gnueabihf-g++ -std=c++11 $1 -o ${1%.*} cp ${1%.*} ~/linux/nfs/ echo "Deployed to NFS" -
串口终端优化:
- 使用screen代替minicom
- 配置串口波特率115200
这套环境搭建方案经过我多个项目的实战检验,相比传统U盘方式,开发效率提升至少3倍。特别是在需要频繁修改和调试的项目中,节省的时间更为可观。
