4. 资源管理基础:资源分类与同步机制
各位同学,咱们今天聊聊资源管理。说实话,这是BSW里最容易出问题的地方之一。我见过太多项目,功能逻辑写得漂漂亮亮,结果一跑多任务就崩了——十有八九是资源管理没做好。
4.1 资源分类:CPU、内存、外设
在AUTOSAR系统里,资源说白了就是三类:CPU时间、内存空间、外设接口。咱们一个一个说。
4.1.1 CPU资源
CPU资源,说白了就是“谁能在哪个时刻用处理器”。在单核系统里,同一时刻只能有一个任务在跑。多任务系统靠调度器来分配CPU时间片。
我个人习惯把CPU资源看作“时间片蛋糕”。每个任务分一块,分多了别的任务饿死,分少了这个任务跑不完。嗯,这里要注意:优先级反转就是典型的CPU资源管理问题。
关键点:CPU资源管理主要靠任务优先级和调度策略。AUTOSAR OS支持优先级抢占调度,高优先级任务可以打断低优先级任务。
4.1.2 内存资源
内存资源分两类:堆(Heap)和栈(Stack)。
- 栈空间:每个任务/ISR有自己的栈。我在项目中遇到过,一个任务栈溢出,把隔壁任务的变量给踩了——查了三天才找到原因。
- 堆空间:动态内存分配用的。AUTOSAR里其实不推荐动态分配,但有些中间件还是会用。
你想想看,嵌入式系统内存就那么点,谁多用一点,别人就少用一点。所以内存管理说白了就是“分蛋糕”的艺术。
4.1.3 外设资源
外设资源包括:CAN控制器、SPI总线、I2C接口、ADC模块等等。这些硬件模块通常不能同时被多个任务访问。
举个例子:两个任务同时往CAN控制器里写数据,会发生什么?数据会乱掉。所以外设资源需要互斥访问。
| 资源类型 | 典型例子 | 管理方式 |
|---|---|---|
| CPU | 任务执行时间 | 优先级调度、时间片 |
| 内存 | 栈、堆、全局变量 | 静态分配、栈监控 |
| 外设 | CAN、SPI、ADC | 资源锁、信号量 |
4.2 资源锁:保护共享资源
资源锁,说白了就是“谁拿到锁谁用”。其他任务想用?等着吧。
AUTOSAR里最常用的资源锁机制是中断锁和调度锁。
4.2.1 中断锁
中断锁就是暂时关闭中断。这样ISR就不会来抢资源了。但要注意:关中断时间不能太长,否则会影响系统实时性。
/* 获取中断锁 */
SuspendAllInterrupts();
/* 访问共享资源 */
shared_data = new_value;
/* 释放中断锁 */
ResumeAllInterrupts();
警告:我曾经在一个项目里,有人把中断锁关了整整1毫秒——结果CAN报文接收超时,整车控制器报故障。关中断时间一定要控制在微秒级。
4.2.2 调度锁
调度锁不关中断,只禁止任务切换。这样ISR还能响应,但其他任务不会来抢资源。
/* 获取调度锁 */
GetResource(SCHEDULER_LOCK);
/* 访问共享资源 */
shared_buffer[index] = data;
/* 释放调度锁 */
ReleaseResource(SCHEDULER_LOCK);
我个人更推荐用调度锁而不是中断锁。为什么呢?因为调度锁不会影响中断响应,系统实时性更好。
4.3 信号量:任务间的同步工具
信号量和资源锁不一样。资源锁是“互斥”的,信号量是“同步”的。
你想想看:一个任务生产数据,另一个任务消费数据。怎么让消费者知道数据准备好了?用信号量。
4.3.1 二值信号量
二值信号量只有两个值:0和1。0表示资源被占用,1表示资源可用。
/* 任务A:生产者 */
while(1) {
/* 生产数据 */
produce_data();
/* 释放信号量,通知消费者 */
ReleaseSemaphore(data_ready);
}
/* 任务B:消费者 */
while(1) {
/* 等待信号量 */
WaitSemaphore(data_ready);
/* 消费数据 */
consume_data();
}
4.3.2 计数信号量
计数信号量可以管理多个同类资源。比如有3个缓冲区,信号量初始值就是3。
小技巧:我建议用信号量时,一定要设置超时。否则任务可能永远等下去——这叫“死锁”。我曾经调试过一个死锁问题,两个任务互相等对方的信号量,系统直接卡死。排查了整整两天。
4.4 资源管理的避坑指南
做资源管理这么多年,我总结了几条经验:
- 能静态分配就别动态分配——动态分配容易产生碎片,而且不好预测。
- 锁的粒度要适中——锁太大,并发性差;锁太小,容易死锁。
- 信号量命名要规范——我见过有人用sema1、sema2这种名字,三个月后自己都看不懂。
- 资源使用要成对出现——获取锁就要释放锁,获取信号量就要释放信号量。
核心原则:资源管理的本质是“谁用谁负责,用完就归还”。别想着别人会帮你释放资源——在嵌入式系统里,没人会帮你擦屁股。
好了,这一章的内容就这些。资源分类、资源锁、信号量,这三个概念是后续章节的基础。下一章咱们聊聊堆栈监控的具体实现——那可是我踩过最多坑的地方。