嵌入式面试复习准备

知识点复习

从内存布局到外设协议,从内核机制到驱动框架------一份面向校招/社招的嵌入式Linux岗位复习指南。


一、内存与指针:别让基础成为你的短板

嵌入式开发离不开对内存的精细控制,面试中指针和数组的区别、存储位置几乎是必考题。

1. 指针变量的存储位置

指针变量本身存放在哪里?这取决于它的存储类型

存储类型 存放位置
局部指针(auto) 栈(Stack)或寄存器
已初始化的全局/静态指针 .data
未初始化的全局/静态指针 .bss

⚠️ 常见陷阱 :指针指向的对象不一定是常量。如果指向字符串字面量(如 char *p = "hello"),字面量位于只读数据段(.rodata),修改它会触发段错误(Segmentation Fault) ,属于未定义行为。但指针本身是可以修改的------你可以让 p 指向别处。

2. 数组的存储与特性

char a[6] = "hello" 为例:

  • 6 字节 (包含结尾 \0),编译器会把字符串字面量拷贝到数组自身的可写空间中
  • 因此 a[i] 可以修改
  • 但数组名 a 是常量地址,不能被重新赋值

数组的存储位置同样取决于存储类型:局部数组在栈上,全局/静态数组按是否初始化分布在 .data.bss 段。

3. Linux 进程内存布局(经典图示)

复制代码
高地址
├─────────────────────────────────
│ 内核空间(用户程序不可访问)
├─────────────────────────────────
│ 栈 (Stack)        ← 局部变量、函数参数、返回地址
│   ↓ 向低地址增长
│
│  (中间空闲区域)
│
│   ↑ 向高地址增长
│ 堆 (Heap)         ← malloc/new 动态分配
├─────────────────────────────────
│ .bss 段           ← 未初始化的全局/静态变量
├─────────────────────────────────
│ .data 段          ← 已初始化的全局/静态变量
├─────────────────────────────────
│ .rodata 段        ← 只读数据(字符串常量等)
├─────────────────────────────────
│ .text 段          ← 程序代码(机器指令)
低地址

4. 内存调试利器:Valgrind Memcheck

面试中常问"你怎么排查内存泄漏?"

Valgrind Memcheck​ 是答案之一。它的核心机制:

  • 拦截 malloc/free 等堆内存管理函数
  • 在堆块前后插入 redzone(红区),记录每一块内存的可访问范围
  • 基于动态二进制插桩影子内存技术

能检测的问题覆盖全面:

检测项 说明
非法读写 越界访问、使用已释放内存
未初始化值使用 读取未初始化的栈/堆变量
重复释放 double free
非法释放 释放非堆指针
内存泄漏 丢失引用的堆内存

二、常见数据结构:环形缓冲区

**环形缓冲区(Ring Buffer / Circular Buffer)**​ 是嵌入式系统中使用频率极高的数据结构:

  • 固定大小、首尾相连的 FIFO(先进先出)结构
  • 想象成一个圆环形数组
  • 读写指针在缓冲区中循环移动,不会真正删除元素,只是覆盖旧数据

典型应用场景:串口数据接收缓冲、音频流缓冲、生产者-消费者模型。


三、外设通信协议:六大总线逐一击破

这是嵌入式面试的重头戏。面试官喜欢让你对比各种总线,或者让你手画时序图。

1. I2C ------ 两线制多主多从

特性 说明
信号线 SCL(时钟)、SDA(数据)
工作模式 半双工、同步、多主多从
速率 100k / 400k / 1M bps
寻址 每个从设备有唯一地址
Linux 框架 I2C 子系统,i2c_client + i2c_driver 匹配
典型应用 传感器、EEPROM、触摸屏控制器

时序要点

  • 空闲时 SCL 和 SDA 均为高电平
  • START:SCL 高电平时 SDA 由高→低
  • STOP:SCL 高电平时 SDA 由低→高
  • 数据在 SCL 低电平期间可变化,SCL 高电平期间必须稳定
  • 每 8 位数据后跟 1 个 ACK/NACK 采样窗口(第 9 个时钟)
  • 支持**重复起始(Repeated START)**切换读写方向
  • 从设备可通过时钟拉伸(拉低 SCL)暂停传输

2. SPI ------ 四线制高速全双工

特性 说明
信号线 SCLK、MOSI、MISO、CS
工作模式 全双工、同步
速率 可达几十 MHz
寻址 无地址概念,靠 CS 片选区分
Linux 框架 spi_master / spi_device / spi_driver
典型应用 Flash、LCD 控制器、高速 ADC、WiFi 模块

时序要点

  • 无统一起始/停止条件,靠 CPOL (时钟极性)和 CPHA(时钟相位)组合成 4 种模式
  • Mode 0:CPOL=0, CPHA=0 → SCLK 空闲低、上升沿采样
  • Mode 3:CPOL=1, CPHA=1 → SCLK 空闲高、上升沿采样
  • 主从在每个 SCLK 周期同时移位:主发 1 位到 MOSI,从返回 1 位到 MISO
  • CS 拉低开始传输,拉高结束;多字节传输时 CS 可保持低
  • 无 ACK 机制,靠硬件保证可靠性

3. UART ------ 异步串口

特性 说明
信号线 TX、RX(可选 RTS/CTS 流控)
工作模式 全双工、异步
速率 双方约定波特率(误差通常 < 2%)
寻址 点对点,无地址/仲裁机制
Linux 框架 TTY 子系统,/dev/ttyS*/dev/ttyAMA*
典型应用 串口终端、GPS、蓝牙模块、调试控制台

帧结构

复制代码
空闲(高) → 起始位(低, 1bit) → 数据位(5~9bit, LSB优先) → 奇偶校验(可选, 1bit) → 停止位(高, 1~2bit)
  • 接收端用本地时钟 16 倍频采样起始位下降沿来同步
  • 硬件流控(RTS/CTS)防止接收端溢出

4. CAN ------ 差分信号、高可靠性

特性 说明
信号线 CAN_H、CAN_L(差分传输)
工作模式 多主竞争、非破坏性仲裁
可靠性 自带 CRC 校验 + 错误重发
Linux 框架 SocketCAN,抽象为网络接口(如 can0
典型应用 汽车电子、工业控制、机器人

标准帧格式

字段 长度 说明
SOF 1 bit 帧起始(显性)
ID 11/29 bit 标识符,值越小优先级越高
RTR 1 bit 远程请求帧标志
IDE 1 bit 扩展帧标志
DLC 4 bit 数据长度 0~8
Data 0~64 bit 有效载荷
CRC 15+1 bit 校验
ACK 2 bit 接收方显性确认
EOF 7 bit 帧结束(全隐性)

5. GPIO ------ 最底层的引脚控制

特性 说明
工作模式 输入、输出、中断、PWM 复用
Linux 框架 GPIO 子系统,gpiod_get() / gpiod_set_value()
用户空间 /sys/class/gpiolibgpiod 工具
典型应用 LED、按键、复位/使能信号

时序场景

  • 输入模式:实时反映外部电平状态
  • 输出模式:写操作立即改变引脚驱动电平
  • 中断模式:边沿/电平触发,外部跳变后数个时钟周期内上报
  • Bit-bang 模式:通过精确延时软件模拟 I2C/SPI 时序
  • PWM 复用:定时器硬件精确控制方波周期和占空比

6. ADC ------ 模拟量采集

特性 说明
功能 模拟电压 → 数字量
Linux 框架 IIO(Industrial I/O)子系统
用户接口 /sys/bus/iio/devices/iio:device0/in_voltage0_raw
典型应用 电池电量、温度采集、电位器输入

逐次逼近型(SAR ADC)工作时序

  1. 采样阶段:采样开关将输入电压存到采样电容
  2. 逐位比较:从 MSB 到 LSB 逐位判决,每 1 位对应 1 个时钟周期
  3. N 位分辨率需 N 个比较周期 + 采样时间
  4. 转换完成置位 EOC(End of Conversion)

换算公式实际电压 = raw_value × (参考电压 / 2^n)

7. PWM ------ 数字方波等效模拟量

原理:硬件定时器驱动计数器累加,计数值 < 阈值输出高,≥ 阈值输出低,溢出归零循环。

  • 占空比 = 高电平时间 ÷ 周期 → 决定等效输出电压/功率
  • Linux PWM 子系统:pwm_config() 设置周期/占空值,pwm_enable() 使能
  • 用户空间:/sys/class/pwm/
  • 典型应用:LED 调光、电机调速、蜂鸣器、背光控制

8. 六大外设对比总结

维度 I2C SPI UART CAN GPIO ADC
信号线数 2 4 2 2(差分) 1+ 1+
双工 半双工 全双工 全双工 半双工 - -
速率 低速 高速 中速 中速 - -
寻址 CS片选 无(点对点) ID仲裁 - -
可靠性 ACK 硬件 校验可选 CRC+重发 - -
典型场景 传感器 Flash 调试终端 汽车/工控 控制 采集

四、内核机制:进程上下文 vs 中断上下文

这是嵌入式 Linux 驱动开发的核心概念,面试必问:

对比维度 进程上下文 中断上下文
进程归属 属于某个进程 无进程归属
能否睡眠 ✅ 可以(可调用调度) ❌ 绝对不能
访问用户空间 ✅ 可以 ❌ 不可以
调度 可能被抢占 不可抢占
典型场景 系统调用、驱动 read/write 中断处理函数(top half)

口诀:中断上下文"三不能"------不能睡眠、不能访问用户空间、不能调用会阻塞的函数。

📚 推荐参考资料

  • 《Linux 设备驱动程序》(LDD3)
  • 《ARM System Developer's Guide》
  • 内核源码:drivers/i2c/drivers/spi/drivers/tty/
  • CSDN / 知乎嵌入式专栏

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 协议,转载请附上原文出处链接。

相关推荐
ShineWinsu1 小时前
对于Git:基础操作的超详细保姆级解析
linux·c++·git·面试·备份·管理·版本控制器
晚安日记wanna2 小时前
Redis 持久化RDB 和 AOF 到底该怎么选
redis·面试·架构
潘潘的嵌入式日记4 小时前
位操作怎么写才不出错?置位、清位、翻转、取位一次讲清
c语言·嵌入式·寄存器·位操作
金士顿5 小时前
ASP.NET Core BackgroundService 深度解析:设备后台任务到底应该怎么设计
linux·嵌入式·asp.net core·arm64
嵌入式阿蔡5 小时前
CRA合规的工程化落地:SBOM、24小时响应与攻击面分析
嵌入式
小刘在重生~5 小时前
十六(3)、《集合扩充》CopyOnWriteArrayList 超详细解析(线程安全集合)
java·笔记·面试·职场和发展
嵌入式阿蔡6 小时前
工业物理AI 2026:从巡检机器人到AI原生工厂
嵌入式
XuCoder6 小时前
LangChain 模型调用:invoke、stream、batch 到底该怎么选?
面试
嵌入式阿蔡6 小时前
边缘AI芯片2026:SoC与协处理器的路线分化
嵌入式