Files
EmbeddedSoftwareLearn1/05-EmbeddedLinux/README.md
T
2025-06-17 14:57:53 +08:00

448 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🟢 第五层:嵌入式 Linux 开发基础
嵌入式 Linux 是物联网、智能设备、工业控制等领域的核心技术之一。本层重点掌握从 Bootloader 到驱动的开发过程,理解 Linux 系统构成及其移植方法。
---
## 🔹 嵌入式 Linux 系统概览
### 📌 嵌入式 Linux 特点
- 可裁剪、可定制、模块化强
- 支持多种架构(ARM、MIPS、RISC-V 等)
- 社区支持强大(开源内核、驱动丰富)
### 📌 系统组成
```text
[Bootloader] → [Kernel] → [Root File System] → [User Application]
```
- **Bootloader**:负责上电后硬件初始化、加载内核(如 U-Boot)
- **Kernel**:Linux 内核,管理硬件与系统资源
- **RootFS**:根文件系统,包含用户空间程序
- **应用层**:运行用户程序、脚本、服务等
---
## 🔹 启动流程详解
### 📌 通用启动流程
```text
Power On →
BootROM →
Bootloader (SPL/U-Boot) →
Load & Decompress Kernel →
Kernel 初始化 →
挂载 RootFS →
启动 init →
Shell / App
```
### 📌 U-Boot(主流 Bootloader)
- 二阶段:SPL(初始化内存)+ U-Boot 本体
- 功能:串口输出、TFTP 下载、引导内核、环境变量配置等
- 命令示例:
```bash
setenv bootargs console=ttyS0 root=/dev/mmcblk0p2
tftp 0x80008000 zImage
bootz 0x80008000 - 0x83000000
```
---
## 🔹 设备树(Device Tree)
### 📌 基本概念
- 描述硬件资源的结构化信息
- 独立于内核源码,提高可移植性
- 文件类型:`.dts`(源文件)、`.dtsi`(包含文件)、`.dtb`(二进制)
### 📌 示例结构
```dts
uart1: serial@40011000 {
compatible = "vendor,uart";
reg = <0x40011000 0x400>;
interrupts = <5>;
status = "okay";
};
```
### 📌 编译设备树
```bash
make ARCH=arm CROSS_COMPILE=arm-linux- dtbs
```
---
## 常用 Linux 命令与开发工具
### 文件与目录管理
| 命令 | 功能说明 |
|-------------------|------------------------------|
| `ls -l` | 列出文件详细信息 |
| `cd /path` | 进入目录 |
| `cp source dest` | 拷贝文件/目录 |
| `mv old new` | 移动/重命名文件 |
| `rm -rf dir` | 删除文件或目录 |
| `mkdir name` | 创建新目录 |
| `find` / `grep` | 搜索文件/内容 |
### 权限与用户管理
| 命令 | 功能说明 |
|--------------------|-----------------------------|
| `chmod 755 file` | 修改权限(rwx) |
| `chown user:group` | 更改文件拥有者 |
| `sudo` | 以管理员身份执行命令 |
| `whoami` / `id` | 查看当前用户信息 |
### 进程管理
| 命令 | 功能说明 |
|------------------|-----------------------------|
| `ps` / `top` | 查看运行进程 |
| `kill PID` | 杀死某个进程 |
| `htop` | 进阶图形化进程管理工具 |
| `nice`, `renice` | 修改进程优先级 |
### 网络调试
| 命令 | 功能说明 |
|------------------------|----------------------------|
| `ping` | 测试网络连通性 |
| `ifconfig` / `ip` | 配置 IP、MAC |
| `netstat -anp` | 查看网络连接状态 |
| `scp`, `rsync` | 文件远程复制 |
| `ssh user@host` | SSH 登录远程系统 |
### 设备与文件系统
| 命令 | 功能说明 |
|----------------------|-----------------------------|
| `mount` / `umount` | 挂载 / 卸载设备 |
| `df -h` | 查看磁盘空间使用情况 |
| `lsblk`, `blkid` | 查看块设备信息 |
| `dmesg | tail` | 查看内核设备日志 |
### 软件包管理(针对开发板所用 Linux)
| 工具 | 说明 |
|--------------------|---------------------------------|
| `apt`, `opkg`, `yum` | 安装 / 卸载软件包 |
| `dpkg -i pkg.deb` | 安装本地 deb 包 |
### Shell 脚本与自动化
- `#!/bin/sh` 或 `#!/bin/bash`:脚本头部声明
- 脚本权限设置:`chmod +x script.sh`
- 示例:
```sh
#!/bin/bash
for i in {1..5}
do
echo "Test $i"
done
```
### 交叉编译相关命令(Makefile 环境)
| 命令/工具 | 说明 |
| --------------- | -------------- |
| `make` | 使用 Makefile 构建 |
| `arm-linux-gcc` | 使用交叉编译器编译 |
| `file a.out` | 查看可执行文件平台架构 |
---
## 🔹 Linux 驱动开发模型
### 📌 驱动分层模型
```text
[硬件设备] ←→ [总线] ←→ [Device] ←→ [Driver] ←→ [内核]
```
- **总线(bus)**:如 platform、i2c、spi 总线
- **设备(device)**:描述具体外设
- **驱动(driver)**:实现对设备的控制逻辑
### 📌 字符设备驱动框架
```c
struct file_operations fops = {
.open = my_open,
.read = my_read,
.write = my_write,
.release = my_release,
};
int major = register_chrdev(0, "mydev", &fops);
```
### 📌 平台驱动开发流程
1. 定义 `platform_device`
2. 编写并注册 `platform_driver`
3. 通过 `of_match_table` 匹配设备树节点
4. 实现 `probe/remove` 等接口
---
## 🔹 根文件系统构建
### 📌 常见文件系统类型
- ext3/ext4:标准 Linux 文件系统
- squashfs:只读压缩文件系统,适合嵌入式
- initramfs:内存文件系统
### 📌 文件系统布局(典型)
```
/
├── bin/ → 常用命令
├── sbin/ → 系统工具
├── etc/ → 配置文件
├── dev/ → 设备节点
├── lib/ → 库文件
├── proc/ → 内核虚拟文件系统
├── sys/ → 设备/驱动信息
├── usr/ → 用户软件
├── tmp/ → 临时目录
└── home/ → 用户主目录
```
### 📌 构建方式
- BusyBox + 自制文件结构
- Buildroot:快速构建定制系统
- Yocto:更灵活、工业级构建方案
---
## 🔹 工具链与调试手段
### 📌 交叉编译工具链
- gcc-arm-linux-gnueabi
- arm-none-eabi-gcc
- 使用环境变量指定:
```bash
export CROSS_COMPILE=arm-linux-
```
### 📌 GDB 调试
- GDB Server + Remote Debug
```bash
gdb-multiarch vmlinux
target remote :1234
```
### 📌 常用调试工具
| 工具 | 用途 |
|-------------|----------------------------|
| GDB | 程序级调试 |
| strace | 跟踪系统调用 |
| dmesg | 内核日志查看 |
| ldd | 查看依赖的库文件 |
| top / htop | 查看系统资源使用情况 |
| lsmod/insmod| 加载/查看内核模块 |
---
## 🔹 常见开发平台
| 平台 | 特点 |
|-------------|------------------------------|
| Raspberry Pi | 社区活跃,支持 Linux 全栈 |
| Allwinner / Rockchip | 国产主控,适配良好 |
| BeagleBone | 支持 PRU、实时协处理器 |
| STM32MP1 | 支持 Linux + Cortex-M 协同 |
---
### 🔹 嵌入式系统安全基础
1. 威胁模型分析
- 物理攻击:
- 探针访问调试接口(JTAG/SWD)读取 Flash 内容。
- 电压 / 时钟干扰导致程序异常(故障注入攻击)。
- 网络攻击:
- 中间人攻击(MITM)篡改通信数据。
- 恶意固件注入(利用未加密 OTA 通道)。
- 软件攻击:
- 缓冲区溢出执行恶意代码。
- 逆向工程获取算法逻辑(如加密密钥)。
2. 安全设计原则
- 最小权限原则:
每个组件仅拥有完成任务所需的最小权限(如 MPU 配置)。
- 防御纵深:
多层次安全机制(如安全启动 + 通信加密 + 运行时防护)。
- 故障安全:
系统在异常情况下自动进入安全状态(如看门狗复位)。
---
### 🔹 安全启动(Secure Boot)
> 保证启动时加载的固件是可信的
1. 基本原理
```plaintext
BootROM → 加载并验证一级Bootloader → 加载并验证二级Bootloader → 加载并验证应用固件
```
- 信任链传递:
每个阶段只信任经过上一阶段验证的代码。
2. 数字签名验证流程
```c
// 简化的签名验证伪代码
bool VerifyFirmwareSignature(uint8_t *firmware, uint32_t size, uint8_t *signature) {
// 1. 从OTP读取可信根公钥
const uint8_t *trusted_public_key = GetTrustedPublicKey();
// 2. 计算固件哈希值
uint8_t calculated_hash[32];
SHA256(firmware, size, calculated_hash);
// 3. 使用公钥解密签名获取原始哈希
uint8_t decrypted_hash[32];
RSA_PKCS1_Verify(trusted_public_key, signature, decrypted_hash);
// 4. 比较哈希值
return (memcmp(calculated_hash, decrypted_hash, 32) == 0);
}
```
3. STM32 Secure Boot 实现
- 选项字节配置:
```c
// 启用读保护(RDP)
HAL_FLASH_OB_Unlock();
FLASH_OBProgramInitTypeDef obInit = {0};
obInit.OptionType = OPTIONBYTE_RDP;
obInit.RDPLevel = OB_RDP_LEVEL_1; // 禁用调试接口
HAL_FLASHEx_OBProgram(&obInit);
HAL_FLASH_OB_Lock();
```
- TrustZone 配置(适用于 STM32L5 等支持型号):
```c
// 配置安全/非安全区域
MPU_Region_InitTypeDef MPU_InitStruct = {0};
// 配置SRAM为安全区域
MPU_InitStruct.Number = MPU_REGION_0;
MPU_InitStruct.BaseAddress = 0x20000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = DISABLE;
MPU_InitStruct.IsShareable = ENABLE;
MPU_InitStruct.IsCacheable = DISABLE;
MPU_InitStruct.IsBufferable = DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
```
---
### 🔹 固件加密与防逆向
1. **AES 加密固件**,防止泄露源码逻辑
- 加密流程:
- 开发阶段:使用工具链(如 GCC 插件)加密固件。
- 部署阶段:Bootloader 解密后加载到 RAM 执行。
- 密钥管理:
- 主密钥存储在 OTP(一次性可编程)区域。
- 会话密钥通过主密钥派生(如 AES-KDF)
2. Flash 读保护(RDP)
| RDP 级别 | 保护效果 | 可逆性 |
|------------|------------------------------------------|-------------------------|
| Level 0 | 无保护(默认) | 是 |
| Level 1 | 禁止调试接口,Flash 只能运行不能读取 | 降级会擦除所有 Flash |
| Level 2 | 永久禁止调试接口和 Flash 读取 | 不可逆 |
3. 代码混淆技术
- 控制流平坦化:
将线性代码转换为基于状态机的结构,增加逆向难度。
- 指令替换:
用等效指令序列替换关键操作(如a+b替换为a-(-b))。
---
### 🔹 权限隔离与防护
1. MPU(内存保护单元)配置
```c
// 配置MPU保护关键数据区
void ConfigureMPU(void) {
// 使能MPU
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
// 配置区域0保护关键代码区
MPU_Region_InitTypeDef MPU_InitStruct = {0};
MPU_InitStruct.Number = MPU_REGION_0;
MPU_InitStruct.BaseAddress = 0x08000000; // Flash起始地址
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RW_URO; // 特权可读写,用户只读
MPU_InitStruct.DisableExec = DISABLE;
MPU_InitStruct.IsShareable = DISABLE;
MPU_InitStruct.IsCacheable = DISABLE;
MPU_InitStruct.IsBufferable = DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
}
```
2. TrustZone 安全域隔离
- 安全资产分类:
| 类别 | 示例 | 存储位置 |
|------------|------------------------------|------------------|
| 密钥 | TLS 私钥、加密密钥 | 安全 SRAM |
| 敏感算法 | 密码验证、加密函数 | 安全代码区 |
| 安全服务 | OTA 签名验证、证书管理 | 安全任务 |
- 安全 / 非安全通信:
```c
// 从非安全代码调用安全服务
__attribute__((section(".nonsecure_call")))
uint32_t SecureService_Call(uint32_t service_id, uint32_t param1, uint32_t param2) {
// 通过SVC指令切换到安全模式
__asm("SVC #0");
// 返回值通过R0传递
}
```
---
### 🔹 Bootloader 开发建议
- 通用功能:下载、校验、重启、回滚
- 支持双分区升级(Slot A / Slot B)
- 防止电量中断、写失败后的砖机风险
- 可设置升级标志位(Upgrade Flag)
---
## 🔚 小结
嵌入式 Linux 是从单片机迈向高性能系统开发的核心门槛,掌握其启动流程、设备树结构与驱动框架是后续学习内核裁剪、系统移植与 IoT 平台开发的基础。