【问题标题】:Function call and context save to stack函数调用和上下文保存到堆栈
【发布时间】:2017-01-25 14:47:51
【问题描述】:

我对微控制器的实时操作系统非常感兴趣,因此我正在对该主题进行深入研究。在高层次上,我了解操作系统的所有一般机制。

为了更好地学习它,我决定编写一个非常简单的内核,它只做上下文切换。这给我提出了很多额外的实际问题。我能够应付其中的许多问题,但我仍然对主要问题存有疑问 - 保存当前任务的上下文(所有 CPU 寄存器和堆栈指针)并恢复新任务的上下文。

一般来说,操作系统使用一些函数(比如 OSContextSwitch()) 来保留上下文切换的所有操作。 OSContextSwitch()的主体主要是用汇编编写的(C体函数中的内联汇编)。但是,当调度程序调用 OSContextSwitch() 时,据我所知,在函数调用中,编译器会在堆栈中保留一些 CPU 寄存器(实际上是由编译器)。

最后,问题是:如何知道编译器已经将哪些 CPU 寄存器保存到堆栈中,以便我可以保留其余的?如果我保留所有寄存器而不考虑编译器行为,显然会有一些堆栈泄漏。

【问题讨论】:

  • 这对我来说并不明显。如果您正在编写代码以将内容推送到堆栈上,那么您是否也在编写代码以将这些内容从堆栈中弹出?因此,只要您弹出您推送的所有内容,那么您应该没问题。如果您推送/弹出不必要的东西,这有什么关系? (或者,“堆栈泄漏”是什么意思?)

标签: function stack rtos


【解决方案1】:

这样的函数应该写成纯汇编(所以NOT是C 函数内的汇编块)或写成只包含汇编块的“裸”C 函数。在这两者之间做任何事情都是把事情搞砸的直接途径。

至于你应该保存的寄存器 - 通常你需要知道你的平台的 ABI,它说一些寄存器由调用者保存,一些应该由被调用者保存 - 你通常只需要保存/恢复那些通常由被调用者保存。如果您将它们全部保存,则不会发生任何错误 - 您的代码只会稍微慢一些并使用更多 RAM,但这是一个很好的起点。

这是 ARM Cortex-M 微控制器的典型上下文切换实现 - https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv6-M-ARMv7-M/ARMv6-M-ARMv7-M-PendSV_Handler.cpp#L76

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    • 2019-08-10
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 2014-07-10
    • 2014-08-30
    相关资源
    最近更新 更多