0

この質問は、オペレーティング システムまたはプラットフォームに依存していると思います。

port オーディオ ライブラリを使用して Windows で C++ コードを書いていたときに発生しました。

ポート オーディオ エンジンに渡されるコールバック関数にあまり多くのコードを記述しないようにドキュメントに記載されています。システムによっては、ISR から呼び出されたり、別のフォーラムを読んだりして、スタックオーバーフロー。

ポート オーディオ固有のことについて質問するつもりはありませんが、メイン関数よりも ISR に多くのコードが記述されている場合、スタック スペースに問題が生じるのはなぜだろうかと考えていました。

コールバックからいくつかの異なる関数を呼び出したいと思います。このコールバックが実際に ISR から呼び出される場合、ISR からさらに多くの関数を呼び出すことは問題になりますか?

各関数を呼び出すと、各関数には独自の最大スタック サイズがあるため、追加のスタック スペースが許可されますか? これは少し混乱します。

関数と ISR は、完全に割り当てられたスタックまで、好きなだけスタック スタック スペースを使用できると常に考えていました。メイン関数が他の関数よりもスタックの大きな部分を持っていることを意味しますか?

よろしくお願いします。

4

4 に答える 4

1

このコールバックが実際に ISR から呼び出される場合、ISR からさらに多くの関数を呼び出すことは問題になりますか?

かもしれない。ISR にはさまざまな種類があり、多くのコンテキストで使用されます。組み合わせによっては、ISR のスタック スペースがかなり制限されます。スタック スペースは、(少なくとも) ISR 自体のパラメーターとローカル変数、およびそれが直接または間接的に呼び出すすべての関数のパラメーターによって使用され、関数呼び出しのオーバーヘッドが伴います。そのスペースは順次関数呼び出しに再利用されますが、ある関数が別の関数を呼び出すと累積されます。

各関数を呼び出すと、各関数には独自の最大スタック サイズがあるため、追加のスタック スペースが許可されますか?

いいえ、一般的にはありません。ISR は、関連付けられているプログラムのスタック空間とは別の独自のスタック空間で呼び出される可能性が非常に高いですが、それは特殊なケースです。関数は通常、呼び出し元と同じスタックを使用しますが、ISRには従来の意味での呼び出し元がありません

関数と ISR は、完全に割り当てられたスタックまで、好きなだけスタック スタック スペースを使用できると常に考えていました。メイン関数が他の関数よりもスタックの大きな部分を持っているということですか?[?]

ISR は、提供されたスタック領域を好きなだけ使用できます。そのスペースは、多くの場合、関連するプログラムのメイン スタックから分離されています。これは、ISR がトリガーされたときにメイン プログラムの状態に干渉するのを避けるのに役立ち、ISR が非同期の場合に不可欠です。分離すると、ISR のスタックは多くの場合、はるかに小さくなります。

プロセスの (メイン) スタックのサイズは、システムによって異なり、場合によっては実行可能ファイルによって異なります。mainから直接または間接的に呼び出される およびすべての関数の間で共有されmainます。シングルスレッド プログラムでmain 、 は他のどの関数よりも多くのスタックにアクセスできますfが、その主な理由はmain(一般に) から までの呼び出しチェーン内のすべての関数が、使用できないスタック スペースmainf占有していることです。f

于 2016-10-12T22:01:34.373 に答える
1

メイン関数よりも ISR に多くのコードが書き込まれている場合、スタック スペースに問題が生じるのはなぜだろうと思っていました。

スタック スペースは、おそらく ISR の主な関心事ではありません。レイテンシを最小限に抑えるために、ISR は可能な限りシンプルかつ高速である必要があるため、とにかく大きなスタックは必要ありません。重要な処理を行う必要がある場合、ISR はタスクをキューに入れ、後で通常のスレッドで実行してジョブを完了する必要があります (上半分と下半分と呼ばれることもあります)。これは、条件変数、セマフォ、またはメッセージ キュー (IPC メカニズムをいくつか挙げると) を使用して実現できます。したがって、ISR が大量のスタックを使用している場合は、タイミングが重要なスケジューリング期間中に過剰な処理を実行しようとしていることを示している可能性があります。

また、多くのシステム (RTOS など) では、スレッドと ISR のスタック サイズを宣言する必要があります。

コールバックからいくつかの異なる関数を呼び出したいと思います。このコールバックが実際に ISR から呼び出される場合、ISR からさらに多くの関数を呼び出すことは問題になりますか?

上記で説明したように、ISR からの他の関数の呼び出しを最小限に抑える必要がある場合に限ります。他の関数を呼び出すことはできますが、ISR がカーネル スケジューラに戻った(およびマスクされていない割り込み!) は、できるだけ実行を延期する必要があります。

また、競合状態に注意してください!共有状態を保護するには、ミューテックスを慎重に使用する必要があります。

各関数を呼び出すと、各関数には独自の最大スタック サイズがあるため、追加のスタック スペースが許可されますか? これは少し混乱します。

いいえ - 関数には独自のスタック サイズがありません - スレッドにはあります。ISR の場合、OS によって異なります。ただし、各関数を呼び出すと、(呼び出しのネスト レベルに基づいて) より多くのスタック スペースが消費されます。

関数と ISR は、完全に割り当てられたスタックまで、好きなだけスタック スタック スペースを使用できると常に考えていました。

はい。ただし、スタックはスレッドごとであり、ヒープのようにプロセスごとではありません。大量のスタック領域を使用することは、設計上の問題の兆候である可能性があります: ヒープではなくスタックに大きなオブジェクトを割り当てる、ネストされた関数呼び出しが多すぎるなど。

メイン関数が他の関数よりもスタックの大きな部分を持っていることを意味しますか?

いいえ、スタックはスレッドごとなので。関数はアプリケーションのmainコール スタックの一番下にありますが、ローカル変数のみに応じて、少量または大量のスタックを消費する場合があります。

いくつかの良い読書:

于 2016-10-13T01:56:12.263 に答える
0

正直なところ、「別のフォーラム」は信用できません。

ドキュメントには、スタック スペースを使いすぎることについては何も書かれていません。これはコードが多すぎるということであり、ISR コールバックのコンテキストでは、ISR で時間がかかりすぎることを意味します。

ISR (コールバックを含む) は、割り込みがブロックされた状態で実行されます。現在、割り込みは蓄積されません。コントローラーは、割り込みが保留中の場合にのみ言うことができます。ISR の実行に時間がかかりすぎると、実行中に発生した割り込みが失われます。

スタック スペースも問題になる可能性がありますが、何よりもまず、コールバックを高速化します。

于 2016-10-13T00:33:30.093 に答える