51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个嵌入式系统的多任务调度与资源管理架构,需考虑任务优先级、资源竞争(如GPIO、ADC)和任务间通信(如信号量、消息队列),请描述核心组件和交互逻辑。

信步科技嵌入式难度:困难

答案

1) 【一句话结论】

采用基于优先级的抢占式调度器,结合资源表管理GPIO、ADC等共享资源,通过信号量实现互斥访问,消息队列实现任务间异步通信,确保任务按优先级执行且资源竞争有序。

2) 【原理/概念讲解】

老师口吻:咱们先拆解核心组件与逻辑。

  • 调度器组件:
    • 就绪队列:存储所有就绪任务,按优先级(数值越小优先级越高)排序。
    • 运行队列:当前正在执行的任务。
    • 等待队列:阻塞任务(如等待资源或消息)。
  • 资源表:记录共享资源(如GPIO、ADC)的状态(空闲/占用)、持有任务ID,用于资源分配与回收。
  • 任务间通信:
    • 信号量:整型变量(0=资源占用,>0=空闲),用于互斥(如GPIO操作)或同步(如任务等待消息)。
    • 消息队列:存储消息的队列,支持异步发送/接收(如ADC数据传输)。

(简短类比:任务如“并行执行的小程序”,资源是“公共设备”,信号量是“锁”,消息队列是“邮件箱”,调度器按优先级分配CPU时间。)

3) 【对比与适用场景】

调度算法对比(优先级 vs 时间片轮转)

算法定义特性使用场景注意点
优先级调度按任务优先级决定运行顺序,高优先级任务抢占低优先级优先级越高,执行优先级越高,实时响应快实时系统(传感器采集、电机控制)可能导致优先级反转,需优先级继承
时间片轮转每个任务分配固定时间片(非抢占)公平,避免任务饥饿用户交互系统(GUI任务)实时性较差,适合非关键任务

通信机制对比(信号量 vs 消息队列)

机制定义特性使用场景注意点
信号量用于同步的整型变量(0=阻塞,>0=空闲)简单高效,操作开销小资源互斥(如GPIO)、任务同步(如等待消息)初始值设置不当可能导致死锁
消息队列存储消息的队列,支持发送/接收异步通信,缓冲区存储消息任务间数据传输(如ADC数据、传感器数据)队列缓冲区溢出需处理

4) 【示例】(伪代码)

// 任务结构体
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(); // 调度器切换任务(从就绪队列取出最高优先级任务)
    }
}

5) 【面试口播版答案】

(约90秒)
“面试官您好,我设计的嵌入式系统多任务调度架构,核心是基于优先级的抢占式调度,通过任务状态管理(就绪/运行/阻塞)和资源表维护,结合信号量(资源互斥)与消息队列(任务间通信),实现多任务公平调度与资源竞争协调。具体来说,系统包含调度器(从就绪队列取出最高优先级任务)、资源管理器(GPIO、ADC资源的互斥访问)。任务创建时分配优先级和资源句柄,调度器按优先级切换任务。对于共享资源(如GPIO),通过信号量实现互斥,避免冲突;对于数据传输(如ADC数据),使用消息队列异步通信。这样既能保证关键任务(如ADC采集)及时执行,又能协调GPIO控制任务,确保系统实时性和可靠性。比如,ADC采集任务(高优先级)先运行,将数据放入队列,GPIO控制任务(低优先级)从队列获取数据后操作GPIO,信号量保证GPIO操作互斥,避免死锁。”

6) 【追问清单】

  1. 问:为什么选择优先级调度而非时间片轮转?
    答:因为嵌入式系统是实时系统,关键任务(如传感器采集)需要优先响应,优先级调度能保证高优先级任务及时执行,避免延迟。

  2. 问:如何处理优先级反转问题?
    答:通过优先级继承机制,被阻塞的高优先级任务会继承阻塞任务的最小优先级,避免低优先级任务阻塞高优先级任务。

  3. 问:信号量与消息队列的区别?
    答:信号量用于同步(互斥或计数),简单高效;消息队列用于异步通信,适合任务间数据传输,避免阻塞关键任务。

  4. 问:资源竞争时,多个任务同时申请GPIO如何处理?
    答:通过信号量实现互斥,任务先申请信号量,操作完成后释放,确保只有一个任务访问GPIO。

  5. 问:调度器如何选择任务?
    答:从就绪队列中取出最高优先级的任务,切换到运行状态,执行任务函数,任务完成后回到就绪队列。

7) 【常见坑/雷区】

  1. 优先级反转:高优先级任务被低优先级任务阻塞,导致系统响应延迟,需用优先级继承解决。
  2. 信号量初始值设置不当:如GPIO信号量初始为0,导致第一个任务无法获取资源,后续任务阻塞。
  3. 队列缓冲区溢出:消息队列缓冲区大小设置过小,导致ADC采集数据时溢出,丢失数据。
  4. 调度器状态管理:未正确维护任务状态(如任务丢失),需明确任务状态(就绪/运行/阻塞)。
  5. 资源释放问题:任务结束后未释放资源(如信号量、队列),导致后续任务无法获取资源,引发死锁。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1