3. 任务管理基础:任务创建、删除、挂起与恢复,任务优先级与调度策略

各位好,咱们今天聊聊任务管理。这是RTOS的核心中的核心。你想想看,光刻机里几十个电机、传感器、执行器要协同工作,靠的就是任务管理来调度。我当年第一次接触尼康的RTOS时,就被它的任务调度机制震撼到了——那叫一个精密。

3.1 任务是什么?

说白了,任务就是一段独立的程序流。每个任务有自己的栈空间、优先级和状态。在尼康的RTOS里,任务的状态分为四种:

  • 运行态:CPU正在执行这个任务
  • 就绪态:任务可以运行,但CPU被别的任务占着
  • 阻塞态:任务在等某个事件(比如信号量、消息队列)
  • 挂起态:任务被主动暂停了,不参与调度

嗯,这里要注意:挂起态和阻塞态不一样。阻塞是任务自己主动等资源,挂起是外部强制让它休息。我在项目中遇到过有人把这两个搞混,结果任务一直不执行,排查了半天。

3.2 任务创建与删除

任务创建,我习惯用 task_create() 这个API。参数包括任务函数指针、栈大小、优先级、任务名等。举个例子:

// 创建一个光刻机对准任务
task_t align_task;
task_create(&align_task, 
            "align_task", 
            align_task_func, 
            NULL, 
            1024, 
            PRIORITY_HIGH, 
            0);

任务删除用 task_delete()。但要注意,删除任务时一定要确保它不再持有任何资源。我曾经有一次删任务时忘了释放互斥锁,结果系统直接死锁了。嗯,血的教训。

警告: 不要在中断服务函数里创建或删除任务。中断上下文和任务上下文不一样,容易出问题。

3.3 任务挂起与恢复

挂起和恢复,说白了就是让任务暂时「睡觉」和「叫醒」。API很简单:

// 挂起任务
task_suspend(align_task);

// 恢复任务
task_resume(align_task);

我个人建议,挂起操作尽量用在调试阶段。生产环境里,我更倾向于用信号量或事件标志来控制任务执行。为什么?因为挂起是强制性的,容易破坏任务间的协作关系。

3.4 任务优先级

优先级是任务调度的核心。尼康的RTOS支持256级优先级,0最高,255最低。我一般这样分配:

优先级范围 用途 示例
0-31 实时性要求极高的任务 电机控制、位置反馈
32-127 普通实时任务 数据采集、状态监控
128-255 后台任务 日志记录、自检

你想想看,如果电机控制任务和日志记录任务优先级一样,那电机抖动一下,晶圆可能就报废了。所以优先级分配一定要谨慎。

3.5 调度策略

尼康的RTOS用的是抢占式优先级调度。什么意思?就是高优先级任务随时可以打断低优先级任务。我画了个图,帮你理解:

时间 任务A(高优先级) 任务A 任务B 任务B B 抢占点 高优先级任务A抢占低优先级任务B

这个图展示了抢占式调度的核心逻辑。任务B正在运行,突然任务A就绪了,CPU立刻切换到任务A。等任务A跑完,再回来继续跑任务B。

核心要点: 抢占式调度保证了高优先级任务的实时性,但也带来了优先级反转的问题。这个问题我们后面章节会专门讲。

3.6 避坑指南

我这些年踩过的坑,总结一下:

  • 栈空间分配:任务栈太小会溢出,太大浪费内存。我一般先给个保守值,然后用工具监测实际使用量。
  • 优先级反转:低优先级任务持有高优先级任务需要的资源,导致高优先级任务被阻塞。解决方案是优先级继承或优先级天花板协议。
  • 任务饿死:低优先级任务永远得不到CPU时间。可以通过时间片轮转或动态优先级调整来解决。
小技巧: 调试阶段,我习惯给每个任务加一个计数器,记录它被调度的次数。这样能直观地看到任务是否被饿死。

好了,任务管理的基础就这些。记住一句话:任务管理是RTOS的骨架,优先级是灵魂。搞懂了这些,你就能驾驭尼康光刻机里的几十个任务了。