第2章:Linux基础与嵌入式开发入门

做嵌入式Linux开发,说白了就是跟Linux系统打交道。我见过不少新手,一上来就急着写代码,结果连文件都传不到板子上,折腾半天。这一章,我把最常用的几个技能点串起来,都是我在项目里每天都要用的东西。

2.1 Linux常用命令回顾

嵌入式开发不像桌面开发,你大部分时间面对的是命令行。嗯,这里没有鼠标,只有键盘。

2.1.1 文件操作三板斧

命令 作用 我常用的参数
ls 列出目录内容 -l 详细列表,-a 显示隐藏文件
cd 切换目录 cd - 回到上一个目录
cp 复制文件/目录 -r 递归复制目录
mv 移动或重命名 源和目标在同一目录就是重命名
rm 删除 -rf 强制递归删除(慎用!)
我曾经在服务器上执行 rm -rf / 时手抖多打了个空格……从那以后,我每次敲 rm -rf 都会先看一眼当前目录。

2.1.2 查看文件内容

  • cat:适合小文件,直接打印到终端
  • more / less:分页查看,less 支持上下翻页和搜索
  • head / tail:只看头尾几行,tail -f 实时跟踪日志

我个人习惯用 less 看代码,用 tail -f 看调试输出。你想想看,嵌入式板子跑起来后,串口日志哗哗地刷,tail -f 就是你的眼睛。

2.1.3 进程与资源查看

  • ps aux:查看所有进程
  • top / htop:动态查看CPU和内存占用
  • free -h:查看内存使用情况
  • df -h:查看磁盘空间
在嵌入式板子上,top 可能没有,但 ps 和 free 基本都有。如果发现进程CPU占用异常,先怀疑是不是死循环了。

2.2 Vim编辑器使用

Vim是嵌入式开发者的标配。别想着在板子上装VS Code,不现实。我刚开始用Vim时也觉得反人类,但用顺手后,效率是真的高。

2.2.1 三种模式

模式 进入方式 作用
普通模式 启动Vim默认进入 移动光标、复制粘贴、删除
插入模式 按 i 输入文本
命令模式 按 : 保存退出、搜索替换

2.2.2 救命操作

  • :wq 保存并退出
  • :q! 不保存强制退出(当你改乱了的时候)
  • dd 删除当前行
  • yy 复制当前行,p 粘贴
  • /关键词 搜索,按 n 跳到下一个
记住:在嵌入式板子上,Vim可能是唯一能用的编辑器。至少学会 i 进入编辑、Esc 退出、:wq 保存退出这三步,你就能活下来。

2.3 Makefile基础

嵌入式项目不可能一个文件搞定。你想想看,几十个源文件,手动编译得累死。Makefile就是告诉编译器:先编译谁,后链接谁。

2.3.1 最简单的Makefile

# 目标: 依赖
hello: hello.c
    gcc -o hello hello.c

clean:
    rm -f hello

执行 make 就会编译,make clean 清理。我在项目中遇到过新手把 clean 写成 clean: 漏了冒号,结果make报错半天找不到原因。

2.3.2 变量与自动推导

CC = arm-linux-gnueabihf-gcc
CFLAGS = -Wall -O2

%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

app: main.o uart.o mqtt.o
    $(CC) $^ -o $@
  • $@ 表示目标文件名
  • $< 表示第一个依赖文件
  • $^ 表示所有依赖文件
交叉编译时,把 CC 换成你的交叉编译器路径。我习惯把编译器路径定义在Makefile顶部,换平台时只改一行。

2.4 SSH与NFS网络文件系统挂载

嵌入式开发中,板子通常没有显示器键盘。你怎么操作它?靠网络。

2.4.1 SSH远程登录

SSH就是给你的板子开一个远程终端。板子连上网络后,你在电脑上执行:

ssh root@192.168.1.100

输入密码,你就进入了板子的命令行。我在项目中经常同时开三个SSH窗口:一个看日志,一个改代码,一个监控系统状态。

2.4.2 NFS挂载

NFS可以把电脑上的一个目录,挂载到板子上。这样你在电脑上改代码,板子上直接就能运行,不用每次都用U盘拷。

电脑端(NFS服务器)配置:

# 编辑 /etc/exports
/home/user/project 192.168.1.0/24(rw,sync,no_subtree_check)

# 重启NFS服务
sudo systemctl restart nfs-kernel-server

板子端(NFS客户端)挂载:

mount -t nfs -o nolock 192.168.1.10:/home/user/project /mnt
我曾经在板子上挂载NFS时忘了加 -o nolock,结果文件锁导致程序崩溃。嵌入式板子的NFS客户端通常不支持锁,加上 nolock 能避免很多坑。

2.5 嵌入式Linux系统启动流程

理解启动流程,你才知道板子从通电到跑起你的程序,中间经历了什么。出了问题也知道去哪查。

嵌入式Linux系统启动流程 ① BootROM ② Bootloader (u-boot) ③ Linux Kernel ④ 根文件系统 (rootfs) ⑤ 用户应用程序 各阶段关键动作 ① 芯片内部固化代码 ② 初始化DDR、加载内核 ③ 解压、挂载根文件系统 常见问题排查点 • 串口无输出 → BootROM • 停在Starting kernel → 内核 • 挂载失败 → rootfs

2.5.1 各阶段详解

  1. BootROM:芯片上电后,内部固件先跑。它初始化最基本的硬件(时钟、片内SRAM),然后去固定的位置(通常是SPI Flash或SD卡)找Bootloader。
  2. Bootloader(u-boot):这是嵌入式开发者的第一道关卡。u-boot初始化DDR、串口、网卡等外设,然后从Flash或网络加载内核到内存,最后跳转到内核入口。
  3. Linux Kernel:内核解压后,初始化所有硬件驱动,挂载根文件系统。如果内核崩溃,通常会在串口打印 Kernel panic。
  4. 根文件系统:内核挂载rootfs后,执行 /sbin/init 程序。init进程是用户空间的第一个进程,PID为1。
  5. 用户应用程序:init根据配置文件(如 /etc/inittab 或systemd的service文件)启动你的MQTT网关程序。
调试技巧:如果板子起不来,看串口打印。停在哪个阶段,问题就在哪个阶段。我排查启动问题,90%靠串口日志,剩下10%靠示波器量电源。

2.5.2 常用启动参数

在u-boot中,你可以设置内核启动参数。我常用的几个:

setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootfstype=ext4'
saveenv
boot
  • console=ttyS0,115200:指定串口终端,波特率115200
  • root=/dev/mmcblk0p2:根文件系统在SD卡第二个分区
  • rw:以读写方式挂载
调试阶段,我习惯用NFS作为根文件系统。这样内核启动后直接挂载电脑上的目录,改代码不用烧写,重启就行。启动参数改成 root=/dev/nfs nfsroot=192.168.1.10:/nfsroot ip=dhcp。

嗯,这一章的内容就这些。命令、编辑器、Makefile、网络挂载、启动流程,都是你后面做MQTT网关项目时每天都要打交道的东西。别急,先练熟这几个基础操作,后面写代码才顺手。