2017-01-25 9 views
0

私はマイクロコントローラのリアルタイムオペレーティングシステムに非常に興味がありますので、私はそのトピックについて深く研究しています。高レベルでは、私はすべてのOSの一般的なメカニズムを理解しています。関数呼び出しとスタックへのコンテキスト保存

これをよりよく理解するために、私はコンテキストスイッチ以外何もしない非常に単純なカーネルを書くことに決めました。これは私に多くの実用的な質問を追加しました。私はそれらの多くに対処することができましたが、私はまだ主なことと疑問に思っています - 現在のタスクのコンテキスト(すべてのCPUレジスタとスタックポインタ)を保存し、新しいタスクのコンテキストを復元します。

一般に、OSはコンテキストスイッチのすべての動作を保持する機能を使用します(OSContextSwitch()))。 OSContextSwitch()の本体は、主にアセンブリで記述されています(C本体関数のインラインアセンブリ)。しかし、OSContextSwitch()がスケジューラによって呼び出されると、私が知る限り、関数呼び出しでは、CPUレジスタのいくつかがコンパイラによって(実際にはコンパイラによって生成されたコードによって)スタック上に保持されます。

最後に、問題は次のとおりです。どのCPUレジスタが既にコンパイラによってスタックに保存されているかを知っているので、残りの部分を保存することができますか?コンパイラの動作に関係なくすべてのレジスタを保持していれば、明らかにスタックリークがあります。

+0

-

はここでARMのCortex-Mマイコン用の典型的なコンテキストスイッチの実装です。あなたがスタックに物をプッシュするコードを書いているのであれば、スタックからその物をポップするコードを書いているわけではありませんか?あなたがプッシュしたすべてをポップする限り、あなたはOKになるはずです。あなたが不必要なものをプッシュ/ポップするとどうなるのですか? (あるいは、「スタックの漏れ」とはどういう意味ですか?) – kkrambo

答えて

0

このような関数は、純粋なアセンブリ(したがって、C関数内のアセンブリブロック)を使用するか、アセンブリブロックだけを使用した "裸の" C関数として記述する必要があります。間に何かをすることは、物事を混乱させるための真っ直ぐな道です。

保存する必要があるレジスタについては、通常、プラットフォームのABIを知っている必要があります。呼び出し元によって保存されるレジスタもあれば、呼び出し先によって保存されるものもあります。通常は被呼者によって保存されるものである。それらをすべて保存すると間違ったことは起こりません - あなたのコードはわずかに遅くなり、もう少しRAMを使いますが、これは始めるのに適しています。それは私には明白ではありませんhttps://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv6-M-ARMv7-M/ARMv6-M-ARMv7-M-PendSV_Handler.cpp#L76

関連する問題