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

说实话,很多做嵌入式Linux网关开发的朋友,最后卡住的往往不是MQTT协议本身,而是Linux环境不熟。我见过太多人,代码写得挺好,一上板子就抓瞎——文件传不上去、编译不过、调试不了。所以这一章,咱们先把地基打牢。

本章核心目标:掌握嵌入式Linux网关开发必备的Linux操作技能,从文件编辑到远程部署,一条龙打通。

2.1 Linux常用命令回顾

嵌入式Linux网关,说白了就是个跑Linux的小电脑。你想想看,没有图形界面,全靠命令行。我个人的习惯是,先把下面这几类命令练到肌肉记忆。

2.1.1 文件与目录操作

命令 用途 我常用的参数
ls 列出目录内容 -la 看隐藏文件,-lh 人性化大小
cd 切换目录 cd - 回到上一个目录
cp 复制文件/目录 -r 递归复制目录
mv 移动/重命名 注意跨文件系统时是复制+删除
rm 删除 -rf 慎用!我吃过亏
find 查找文件 -name "*.c" 按名字找
我曾经犯过的错:在开发板上执行 rm -rf / 少打了个点。嗯,从那以后我养成了习惯——每次敲 rm 之前,先 ls 确认一下路径。

2.1.2 进程与系统监控

网关设备跑起来之后,你最关心的就是:CPU占了多少?内存够不够?哪个进程在吃资源?

  • top / htop:实时看进程,按 P 按CPU排序,按 M 按内存排序
  • ps aux:快照式查看所有进程,配合 grep 找特定进程
  • free -h:看内存使用,注意 available 才是真正可用的
  • df -h:看磁盘空间,嵌入式设备Flash通常很小
  • netstat -tlnp:看端口监听,MQTT broker默认1883端口
小技巧:我习惯用 watch -n 1 'netstat -tlnp' 每秒刷新一次,调试网络服务时特别好用。

2.1.3 网络调试三件套

做网关开发,网络调试是家常便饭。这三个命令我几乎每天用:

  1. ping:先确认网络通不通。注意嵌入式设备ping大包可能会卡死
  2. ifconfig / ip addr:看IP地址、MAC地址。我更喜欢 ip 命令,信息更全
  3. tcpdump:抓包神器。比如抓MQTT报文:tcpdump -i eth0 port 1883 -X

2.2 Vim编辑器使用

在嵌入式Linux上,没有VS Code,没有Sublime。你只能靠Vim或者Nano。我个人强烈建议学Vim——虽然入门曲线陡,但熟练之后效率极高。

2.2.1 三种模式

Vim的核心就三个模式,搞懂这个你就入门了:

模式 进入方式 能做什么
普通模式 启动Vim默认进入 移动光标、复制粘贴、删除
插入模式 按 i 输入文字
命令模式 按 : 保存退出、搜索替换
记住这个口诀:按 i 进插入,按 Esc 回普通,按 : 输命令。

2.2.2 我常用的Vim操作

刚开始别贪多,先记住这几个就够用了:

  • gg:跳到文件开头
  • G:跳到文件末尾
  • dd:删除当前行
  • yy:复制当前行,p 粘贴
  • /keyword:搜索关键字,按 n 下一个
  • :wq:保存退出
  • :q!:不保存强制退出
避坑指南:我曾经在嵌入式设备上编辑配置文件,按了 Ctrl+S 想保存——结果终端卡死了!因为 Ctrl+S 是终端锁屏。按 Ctrl+Q 解锁。这个坑我踩过三次才记住。

2.3 Makefile基础

嵌入式Linux网关的代码,通常要在PC上交叉编译,然后传到板子上跑。Makefile就是管理编译过程的脚本。说白了,它告诉编译器:先编译哪个文件,链接哪些库,生成什么目标。

2.3.1 一个最简单的Makefile

# 最简单的Makefile
all: hello

hello: hello.c
    gcc -o hello hello.c

clean:
    rm -f hello

这个例子虽然简单,但包含了Makefile的核心三要素:目标(target)、依赖(prerequisites)、命令(recipe)。

2.3.2 嵌入式交叉编译的Makefile

在实际项目中,我们不会用PC的gcc,而是用交叉编译器。比如给ARM架构的网关编译:

# 交叉编译Makefile示例
CROSS_COMPILE = arm-linux-gnueabihf-
CC = $(CROSS_COMPILE)gcc
CFLAGS = -Wall -O2 -I./include
LDFLAGS = -L./lib -lpaho-mqtt3c

TARGET = mqtt_gateway
SRCS = main.c mqtt_client.c sensor.c
OBJS = $(SRCS:.c=.o)

all: $(TARGET)

$(TARGET): $(OBJS)
    $(CC) -o $@ $^ $(LDFLAGS)

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

clean:
    rm -f $(OBJS) $(TARGET)

.PHONY: all clean
关键点:$@ 表示目标文件,$^ 表示所有依赖,$< 表示第一个依赖。这三个自动变量我几乎每个Makefile都会用。

2.4 SSH与SCP远程操作

网关设备通常没有显示器键盘,你只能通过网络远程操作。SSH和SCP就是你的双手。

2.4.1 SSH远程登录

基本用法:

ssh root@192.168.1.100

第一次连接会提示确认指纹,输入 yes 就行。我建议配置SSH密钥登录,省得每次输密码:

# 在PC上生成密钥
ssh-keygen -t rsa -b 4096

# 把公钥传到板子上
ssh-copy-id root@192.168.1.100

2.4.2 SCP文件传输

从PC传文件到板子:

scp mqtt_gateway root@192.168.1.100:/home/

从板子拉文件到PC:

scp root@192.168.1.100:/var/log/syslog ./

传整个目录加 -r:

scp -r config/ root@192.168.1.100:/etc/mqtt/
注意:嵌入式设备的Flash写入寿命有限。我习惯先 scp 到 /tmp(内存文件系统),确认没问题再拷到Flash里。

2.5 NFS网络文件系统挂载

开发阶段最痛苦的是什么?每次改一行代码,就要重新编译、scp上传、重启程序。用NFS可以解决这个问题——把PC上的目录直接挂载到板子上,板子运行的就是PC上的文件。

2.5.1 搭建NFS服务器(PC端)

以Ubuntu为例:

# 安装NFS服务器
sudo apt install nfs-kernel-server

# 创建共享目录
mkdir ~/nfs_root

# 编辑配置文件
sudo vim /etc/exports

# 添加一行(假设板子IP是192.168.1.100)
/home/username/nfs_root 192.168.1.100(rw,sync,no_subtree_check,no_root_squash)

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

2.5.2 板子上挂载NFS

# 创建挂载点
mkdir /mnt/nfs

# 挂载(假设PC IP是192.168.1.10)
mount -t nfs -o nolock 192.168.1.10:/home/username/nfs_root /mnt/nfs

# 验证
ls /mnt/nfs
我的经验:加上 -o nolock 是因为很多嵌入式板子的NFS客户端不支持文件锁。不加这个参数,挂载会失败。

2.5.3 开发工作流

有了NFS,开发流程变成这样:

  1. 在PC上写代码、编译
  2. 把编译好的文件放到 ~/nfs_root 目录
  3. 在板子上直接运行 /mnt/nfs/your_program
  4. 改代码 → 重新编译 → 直接运行,不用再传文件

效率提升不是一点半点。我当年做一个网关项目,前期没用NFS,每天光传文件就浪费半小时。后来配好NFS,一天能多调好几个bug。

2.6 本章知识体系

下面这张图把本章的核心知识点串起来了:

嵌入式Linux网关开发环境知识体系 开发环境基础 Linux常用命令 Vim编辑器 Makefile基础 SSH与SCP远程操作 NFS网络文件系统 文件操作 进程监控 网络调试 交叉编译 远程部署 核心思路:PC端开发 → 交叉编译 → 远程部署/挂载 → 板端运行调试 NFS可省去重复传文件步骤,大幅提升开发效率

这五个技能点,就像盖房子的五根柱子。Linux命令是地基,Vim是砌墙的瓦刀,Makefile是施工图纸,SSH/SCP是运输车,NFS是脚手架。缺了哪根,干活都不顺手。

嗯,这一章的内容就到这里。把这些练熟了,后面讲MQTT协议集成的时候,你就能把精力放在协议本身,而不是被环境问题绊住脚。