第三章:Linux基础与Shell编程
说实话,很多刚入行的朋友问我:「做TBOX开发,Linux要学到什么程度?」我的回答很简单——你不需要成为内核专家,但命令行和脚本是吃饭的家伙。今天这一章,我就把最常用的东西拎出来,都是我在项目里反复用到的。
3.1 常用Linux命令
先说说几个高频命令。嗯,这些命令我每天至少用几十次。
3.1.1 ls - 列出文件
ls 是最基础的命令。但我建议你养成加参数的习惯:
ls -l # 长格式显示,能看到权限、大小、时间
ls -a # 显示隐藏文件(以.开头的文件)
ls -lh # 人类可读的大小(K、M、G)
ls -lt # 按时间排序,最新的在最上面
我的习惯: 我一般直接用 ll(其实是 ls -l 的别名)。在嵌入式开发中,经常用 ls -l /dev/ 查看设备节点,确认外设驱动是否加载成功。
3.1.2 cd - 切换目录
这个太基础了,但有几个技巧值得记住:
cd ~ # 回到家目录
cd - # 回到上一个目录,超实用
cd .. # 上一级目录
cd ../../ # 上两级
我在项目中经常用 cd - 在编译目录和源码目录之间快速切换。你想想看,省了多少打字时间。
3.1.3 ps - 查看进程
做TBOX开发,进程管理是家常便饭。我常用的组合:
ps aux # 查看所有进程
ps aux | grep tbox # 过滤出TBOX相关进程
ps -ef # 另一种格式
注意: 我曾经在调试时发现TBOX进程莫名其妙消失了,用 ps aux 一看,原来是内存不足被OOM killer干掉了。所以,没事多看看进程状态。
3.1.4 top - 系统监控
top 是实时监控神器。按 1 可以看每个CPU核心的使用率,按 M 按内存排序,按 P 按CPU排序。
top -d 1 # 每秒刷新一次
top -p 1234 # 只监控PID为1234的进程
在TBOX上,我经常用 top 看哪个进程在偷吃CPU。有一次发现某个通信模块占用了80%的CPU,一查是死循环了。
3.1.5 netstat - 网络状态
TBOX离不开网络通信。netstat 是我排查网络问题的第一工具:
netstat -tlnp # 查看TCP监听端口
netstat -ulnp # 查看UDP监听端口
netstat -anp # 查看所有连接
实战场景: 我记得有一次TBOX上报数据失败,用 netstat -tlnp 一看,发现MQTT客户端根本没连上服务器端口。原来是防火墙把端口封了。
3.2 Vim编辑器的使用
说到Vim,很多新手觉得难。但说实话,在嵌入式Linux上,你逃不掉的。没有图形界面,Vim就是你的IDE。
3.2.1 三种模式
Vim有三种模式,搞懂了就入门了:
| 模式 | 作用 | 如何进入 |
|---|---|---|
| 普通模式 | 移动光标、复制粘贴 | 默认模式,按 Esc 返回 |
| 插入模式 | 输入文字 | 按 i 进入 |
| 命令模式 | 保存退出、搜索替换 | 按 : 进入 |
3.2.2 我常用的操作
i # 在光标前插入
dd # 删除当前行
yy # 复制当前行
p # 粘贴
:wq # 保存并退出
:q! # 不保存强制退出
/xxx # 搜索xxx
:%s/old/new/g # 全局替换
我的建议: 刚开始别学太多,记住 i、:wq、dd、yy、p 这五个就够了。其他的慢慢来。我曾经带过一个新人,第一天就背了50个Vim命令,结果一个都没记住。
3.3 Shell脚本基础
Shell脚本是自动化利器。在TBOX开发中,我经常用它来写启动脚本、日志清理、批量测试。
3.3.1 变量
Shell变量不需要声明类型,直接用:
#!/bin/bash
# 这是我的第一个脚本
NAME="TBOX_DEVICE"
VERSION="1.0.0"
echo "设备名称: $NAME"
echo "版本号: $VERSION"
# 命令替换
CURRENT_TIME=$(date)
echo "当前时间: $CURRENT_TIME"
注意: 变量赋值时等号两边不能有空格!我刚开始写脚本时,经常写成 NAME = "xxx",结果报错半天找不到原因。
3.3.2 循环
循环在批量处理时特别好用:
#!/bin/bash
# for循环 - 遍历文件
for file in /var/log/*.log; do
echo "处理日志: $file"
done
# while循环 - 读取文件
while read line; do
echo "读取到: $line"
done < /etc/config/tbox.conf
3.3.3 条件判断
条件判断让脚本有了「脑子」:
#!/bin/bash
# 判断文件是否存在
if [ -f "/etc/tbox.conf" ]; then
echo "配置文件存在"
else
echo "配置文件不存在,创建默认配置"
touch /etc/tbox.conf
fi
# 判断进程是否运行
if pgrep -x "tbox_main" > /dev/null; then
echo "TBOX主进程正在运行"
else
echo "TBOX主进程未运行,启动中..."
/usr/bin/tbox_main &
fi
实战经验: 我曾经写过一个监控脚本,每隔5分钟检查TBOX的4G模块是否在线。如果掉线就自动重启模块。这个脚本帮我省了不少半夜爬起来处理故障的麻烦。
3.4 Makefile的编写入门
Makefile是C/C++项目的构建工具。说白了,就是告诉编译器怎么编译你的代码。
3.4.1 最简单的Makefile
# 目标:依赖
# 命令(前面必须是Tab)
tbox_app: main.o network.o mqtt.o
gcc -o tbox_app main.o network.o mqtt.o -lpthread -lmqtt
main.o: main.c
gcc -c main.c
network.o: network.c
gcc -c network.c
mqtt.o: mqtt.c
gcc -c mqtt.c
clean:
rm -f *.o tbox_app
3.4.2 使用变量和模式规则
上面的写法太啰嗦了。实际项目中我这样写:
CC = arm-linux-gnueabihf-gcc
CFLAGS = -Wall -O2 -I./include
LDFLAGS = -lpthread -lmqtt
TARGET = tbox_app
SRCS = main.c network.c mqtt.c
OBJS = $(SRCS:.c=.o)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: clean
解释一下: $@ 表示目标文件,$^ 表示所有依赖,$< 表示第一个依赖。这些自动化变量能省不少事。我刚开始学Makefile时,就是被这些符号搞晕的,但用多了就习惯了。
3.4.3 交叉编译的Makefile
做TBOX开发,代码是在PC上编译,在ARM板子上运行。所以Makefile要指定交叉编译器:
# 交叉编译工具链
CROSS_COMPILE = arm-linux-gnueabihf-
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar
STRIP = $(CROSS_COMPILE)strip
CFLAGS = -Wall -O2 -march=armv7-a
LDFLAGS = -lpthread -lrt
TARGET = tbox_app
SRCS = main.c network.c mqtt.c
OBJS = $(SRCS:.c=.o)
all: $(TARGET)
$(STRIP) $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
install:
cp $(TARGET) /tftpboot/
踩坑提醒: 我曾经犯过一个低级错误——在PC上编译通过的程序,拷到ARM板子上跑不起来。后来发现是忘了用交叉编译器。记住:PC的gcc编译出来的程序,ARM板子跑不了!
小结
这一章的内容,说白了就是TBOX开发的「基本功」。Linux命令让你能操作设备,Vim让你能编辑代码,Shell脚本让你能自动化任务,Makefile让你能构建项目。这四个技能,缺一不可。
我个人建议,别急着一次性全记住。先上手用,遇到问题再回来查。我在项目里也是这么过来的——用多了自然就熟了。
下一章,我们会进入真正的TBOX应用开发。到时候,这些基础都会派上用场。