2. 嵌入式Linux与工业场景基础

做嵌入式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调试
注意:网络模式一定要选桥接。NAT模式虽然能上网,但宿主机连不上虚拟机,后面做NFS根文件系统挂载时会很痛苦。我曾经在这上面浪费了半天。

2.1.2 Ubuntu版本选择

我推荐Ubuntu 20.04 LTS或22.04 LTS。别追新,LTS版本稳定,社区支持好,交叉编译链的兼容性问题少。18.04也行,但有些新工具链需要更新的glibc,会比较麻烦。

小技巧:装完系统后,第一件事就是换国内源。阿里云、清华、中科大的源都行。不然apt update能等到你怀疑人生。

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/               # 自己写的编译脚本
建议:交叉编译链不要放在系统目录(如/usr/local),放在用户目录下。这样换电脑或重装系统时,直接拷贝整个workspace就能恢复环境。

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 开发环境知识体系

下面这张图,帮你理清开发环境各组件之间的关系:

嵌入式Linux开发环境知识体系 宿主机(Windows / Mac) Ubuntu虚拟机(VMware / VirtualBox) 开发工具:Git + Vim + SSH + Build Tools 内核源码 U-Boot / Buildroot 交叉编译链 编译产物:zImage / dtb / ko / rootfs 目标开发板(ARM / ARM64) 工作目录规划 ~/workspace/ 按项目分类管理

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内核,结果某些内联汇编语法不兼容,折腾了两天。

环境搭好了,后面编译内核、写驱动、调试,才能顺风顺水。别急,一步一步来。