
采用基于优先级的抢占式调度器,结合资源表管理GPIO、ADC等共享资源,通过信号量实现互斥访问,消息队列实现任务间异步通信,确保任务按优先级执行且资源竞争有序。
老师口吻:咱们先拆解核心组件与逻辑。
(简短类比:任务如“并行执行的小程序”,资源是“公共设备”,信号量是“锁”,消息队列是“邮件箱”,调度器按优先级分配CPU时间。)
| 算法 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 优先级调度 | 按任务优先级决定运行顺序,高优先级任务抢占低优先级 | 优先级越高,执行优先级越高,实时响应快 | 实时系统(传感器采集、电机控制) | 可能导致优先级反转,需优先级继承 |
| 时间片轮转 | 每个任务分配固定时间片(非抢占) | 公平,避免任务饥饿 | 用户交互系统(GUI任务) | 实时性较差,适合非关键任务 |
| 机制 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 信号量 | 用于同步的整型变量(0=阻塞,>0=空闲) | 简单高效,操作开销小 | 资源互斥(如GPIO)、任务同步(如等待消息) | 初始值设置不当可能导致死锁 |
| 消息队列 | 存储消息的队列,支持发送/接收 | 异步通信,缓冲区存储消息 | 任务间数据传输(如ADC数据、传感器数据) | 队列缓冲区溢出需处理 |
// 任务结构体
typedef struct {
uint8_t priority; // 优先级(数值越小优先级越高)
void (*task_func)(void); // 任务函数
uint8_t state; // 0:就绪, 1:运行, 2:阻塞
Semaphore *gpio_sem; // GPIO互斥信号量(初始值1,表示空闲)
Queue *adc_queue; // ADC数据消息队列(缓冲区大小设为10)
} Task;
// 初始化系统
void system_init() {
scheduler_init(); // 初始化调度器(就绪/运行/等待队列)
gpio_sem = sem_create(1); // GPIO信号量:1=空闲,0=占用
adc_queue = queue_create(10); // ADC队列缓冲区大小为10
}
// 创建任务
void task_create(uint8_t priority, void (*func)(void)) {
Task *t = malloc(sizeof(Task));
t->priority = priority;
t->task_func = func;
t->state = READY;
t->gpio_sem = gpio_sem;
t->adc_queue = adc_queue;
scheduler_add_task(t); // 添加到调度器就绪队列
}
// ADC采集任务(高优先级,实时性要求高)
void adc_task(void) {
while (1) {
uint16_t data = adc_read(); // 读取ADC数据
queue_send(adc_queue, data); // 异步发送数据到队列
}
}
// GPIO控制任务(低优先级,非实时性)
void gpio_task(void) {
while (1) {
sem_wait(gpio_sem); // 等待GPIO可用(互斥)
gpio_set_pin(1, HIGH); // 操作GPIO
delay(100);
gpio_set_pin(1, LOW);
sem_post(gpio_sem); // 释放GPIO
}
}
// 主循环(调度器循环)
int main() {
system_init();
task_create(1, adc_task); // 高优先级:ADC采集
task_create(2, gpio_task); // 低优先级:GPIO控制
while (1) {
scheduler(); // 调度器切换任务(从就绪队列取出最高优先级任务)
}
}
(约90秒)
“面试官您好,我设计的嵌入式系统多任务调度架构,核心是基于优先级的抢占式调度,通过任务状态管理(就绪/运行/阻塞)和资源表维护,结合信号量(资源互斥)与消息队列(任务间通信),实现多任务公平调度与资源竞争协调。具体来说,系统包含调度器(从就绪队列取出最高优先级任务)、资源管理器(GPIO、ADC资源的互斥访问)。任务创建时分配优先级和资源句柄,调度器按优先级切换任务。对于共享资源(如GPIO),通过信号量实现互斥,避免冲突;对于数据传输(如ADC数据),使用消息队列异步通信。这样既能保证关键任务(如ADC采集)及时执行,又能协调GPIO控制任务,确保系统实时性和可靠性。比如,ADC采集任务(高优先级)先运行,将数据放入队列,GPIO控制任务(低优先级)从队列获取数据后操作GPIO,信号量保证GPIO操作互斥,避免死锁。”
问:为什么选择优先级调度而非时间片轮转?
答:因为嵌入式系统是实时系统,关键任务(如传感器采集)需要优先响应,优先级调度能保证高优先级任务及时执行,避免延迟。
问:如何处理优先级反转问题?
答:通过优先级继承机制,被阻塞的高优先级任务会继承阻塞任务的最小优先级,避免低优先级任务阻塞高优先级任务。
问:信号量与消息队列的区别?
答:信号量用于同步(互斥或计数),简单高效;消息队列用于异步通信,适合任务间数据传输,避免阻塞关键任务。
问:资源竞争时,多个任务同时申请GPIO如何处理?
答:通过信号量实现互斥,任务先申请信号量,操作完成后释放,确保只有一个任务访问GPIO。
问:调度器如何选择任务?
答:从就绪队列中取出最高优先级的任务,切换到运行状态,执行任务函数,任务完成后回到就绪队列。