2. 开发环境搭建:Ubuntu虚拟机配置、必备工具安装、工作目录规划
做嵌入式Linux开发,环境搭建是第一道坎。很多新手在这上面折腾好几天,结果发现是虚拟机网络没配好,或者交叉编译链路径写错了。我个人习惯先把地基打牢,后面才省心。
这一节,我带你一步步把开发环境搭起来。嗯,都是我在项目里反复验证过的做法。
2.1 Ubuntu虚拟机配置
为什么选虚拟机?因为方便。你可以在Windows/Mac上跑Linux,随时快照、随时恢复。我建议用VMware Workstation Pro或VirtualBox,两者都行。我个人偏向VMware,稳定,而且和USB设备的兼容性好一些。
2.1.1 虚拟机硬件分配
别贪心。不是给得越多越好。给虚拟机太多资源,宿主机反而卡。我一般这样分配:
| 硬件项 | 推荐配置 | 说明 |
|---|---|---|
| CPU核心数 | 2-4核 | 编译内核时多核有用,但别超过宿主机一半 |
| 内存 | 8GB | 4GB勉强够,8GB编译大型项目才不卡 |
| 磁盘 | 80GB-120GB | 动态分配,实际用多少占多少 |
| 网络 | 桥接模式 | 让虚拟机独立IP,方便SSH和NFS调试 |
2.1.2 Ubuntu版本选择
我推荐Ubuntu 20.04 LTS或22.04 LTS。别追新,LTS版本稳定,社区支持好,交叉编译链的兼容性问题少。18.04也行,但有些新工具链需要更新的glibc,会比较麻烦。
2.2 必备工具安装
系统装好了,接下来装工具。这些是嵌入式Linux开发的标配,缺一不可。
2.2.1 Git:版本控制
Git不只是用来拉代码的。你在调试驱动时,经常需要回退、对比、打补丁。没有Git,你改了几行代码自己都记不住。
sudo apt update
sudo apt install git git-lfs
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
git config --global core.editor vim
为什么要装git-lfs?因为内核源码里有些大文件(比如firmware),不用LFS拉下来会非常慢。我在一个项目里拉4.19内核,没装LFS,等了快一个小时。
2.2.2 Vim:编辑器
Vim是嵌入式工程师的标配。你SSH到开发板上,没有图形界面,只能用终端编辑器。Vim学习曲线陡,但值得投入。
sudo apt install vim
# 配置一个基本的.vimrc
cat >> ~/.vimrc << EOF
set number
set tabstop=4
set shiftwidth=4
set expandtab
syntax on
filetype plugin indent on
EOF
我的习惯:Vim配合ctags和cscope,看内核源码非常高效。你想想看,一个驱动文件几千行,没有跳转功能,找函数定义得翻半天。
2.2.3 SSH:远程连接
SSH是嵌入式调试的生命线。你编译好的内核和驱动,要通过SSH传到开发板上。你还要SSH到开发板上去看dmesg、调试驱动。
sudo apt install openssh-server openssh-client
# 启动SSH服务
sudo systemctl enable ssh
sudo systemctl start ssh
# 检查状态
sudo systemctl status ssh
这里有个坑:虚拟机默认可能没开SSH服务。你装完一定要检查一下。我曾经在客户现场,发现开发板连不上虚拟机,折腾了半天才发现是SSH没启动。
2.2.4 其他必备工具
这些工具我几乎每天都会用到:
- build-essential:编译工具链,gcc、g++、make都在里面
- ncurses-dev:内核menuconfig配置界面需要
- flex、bison:内核编译的语法分析器
- libssl-dev:内核模块签名需要
- nfs-kernel-server:NFS服务,用于根文件系统挂载
- tftp-hpa、tftpd-hpa:TFTP服务,用于网络启动内核
sudo apt install build-essential libncurses-dev flex bison libssl-dev \
nfs-kernel-server tftp-hpa tftpd-hpa
2.3 工作目录规划
这一点很多人不重视。项目做大了,目录乱成一锅粥,找个文件要半天。我有一套固定的目录结构,用了好几年,分享给你。
2.3.1 顶层目录结构
我在家目录下建一个workspace文件夹,里面按项目分:
~/workspace/
├── linux-5.10.y/ # 内核源码
├── uboot/ # U-Boot源码
├── buildroot/ # Buildroot根文件系统
├── toolchain/ # 交叉编译链
│ ├── gcc-arm-9.2/ # ARM交叉编译链
│ └── gcc-aarch64-9.2/ # ARM64交叉编译链
├── drivers/ # 自己写的驱动
│ ├── gpio-led/
│ ├── i2c-sensor/
│ └── spi-flash/
├── rootfs/ # 制作好的根文件系统
├── images/ # 编译好的镜像
│ ├── zImage
│ ├── uImage
│ └── rootfs.ext4
└── scripts/ # 自己写的编译脚本
2.3.2 环境变量配置
每次编译都要设置交叉编译链路径,很烦。我把它写到~/.bashrc里:
# 在 ~/.bashrc 末尾添加
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:$HOME/workspace/toolchain/gcc-arm-9.2/bin
# 生效
source ~/.bashrc
为什么要单独建一个scripts/目录?因为编译命令往往很长,而且参数容易忘。我习惯写一个build_kernel.sh脚本,把编译、打包、部署一条龙搞定。
2.4 开发环境知识体系
下面这张图,帮你理清开发环境各组件之间的关系:
2.5 验证环境
装完所有工具后,我习惯跑一个快速验证脚本,确保环境没问题:
# 1. 检查Git
git --version
# 2. 检查Vim
vim --version | head -1
# 3. 检查SSH
ssh -V
# 4. 检查交叉编译链(如果有)
arm-linux-gnueabihf-gcc --version
# 5. 检查内核源码(如果有)
ls ~/workspace/linux-5.10.y/Makefile
核心思路:开发环境搭建不是一次性工作。每加一个新项目,都要检查工具链版本是否兼容。我见过有人用gcc 9.2编译Linux 4.19内核,结果某些内联汇编语法不兼容,折腾了两天。
环境搭好了,后面编译内核、写驱动、调试,才能顺风顺水。别急,一步一步来。