我只是急切地想知道当一些异步事件引发ISR以使更高优先级的任务准备好运行时,OS实际上如何进行上下文切换。据我所知,当CPU进入ISR时,它会将一些寄存器值放入硬件堆栈,那么调度程序如何将这些值转发并将其放入任务堆栈?它是否访问硬件堆栈以复制已经保留的值?我希望我很清楚。
提前致谢。
答案 0 :(得分:2)
在Cortex-M3处理器上,您有MSP(主堆栈指针 - 这是您的硬件堆栈)和PSP(进程堆栈指针 - 这是您的任务堆栈)。
在进入异常时,堆栈帧存储在当前PSP堆栈中(在正常的非嵌套操作中)。异常处理程序然后切换到MSP堆栈,但它仍然可以访问PSP堆栈,因此它可以在同一个PSP堆栈上存储任何剩余的寄存器等,以及它需要的任何其他任务信息。
然后异常可以选择新的高优先级任务并将PSP切换到此任务堆栈并恢复所需的寄存器。然后它使PSP处于与任务暂停时完全相同的状态,以便在从异常返回时正确恢复堆栈的其余部分。
在某些情况下它比这更复杂,但这是基本操作(在ARM Cortex-M上)。在其他处理器上会有所不同。
我建议下载FreeRTOS并查看各种不同的端口层。几乎所有东西都有一个端口,“便携式”目录中的低级任务切换功能相当小而直接。
答案 1 :(得分:2)
由于我不太确定你问题的范围是什么,我将尝试总结一些先发制人安排的概念:
每个任务有一个堆栈。对于每个堆栈,都有一个指向它的堆栈指针。所以基本上,对于任务切换,保存当前堆栈指针并加载下一个任务的堆栈指针。有趣的是,从操作系统到任务代码的返回是通过RETURN
指令完成的,而不是像人们期望的那样JUMP
或CALL
。
当ISR中断正在运行的任务时,它不会自己运行另一个任务。正如您所说,它只会使一个任务 runnable (将其从等待状态中取出),这样,在下一个调度周期中,操作系统可以考虑现在 - 准备好进一步执行的任务。 (如果该任务的运行取决于其分配的优先级;如果它具有非常高的优先级,则操作系统可以尝试确保它在任何其他较低的prio任务切换到之前运行。)
实际任务切换仅在完成并返回ISR后发生,因此无需将任何内容从一个堆栈复制到另一个堆栈。
在“简单”实现中,ISR可能只返回它中断的任务,因此不会发生早期的“无序”上下文切换。
另一个更复杂的实现可以让ISR返回操作系统而不是中断的任务。因此可以调用类似yield()
的函数,如果需要,OS可以立即执行任务切换。
但是,这可能要求受影响的ISR附加特殊的退出指令,替换正常的编译器生成的ISR代码。