Cのprintf()はISRでは使用されないはずだと聞きました。それはブロッキング呼び出しであるためですか、それとも再入可能ではないためですか?
printf()が再入可能でない場合、何らかの方法で「同期」されていない限り、マルチスレッドプログラムにも使用できないことを意味しませんか?
ありがとう、
Cのprintf()はISRでは使用されないはずだと聞きました。それはブロッキング呼び出しであるためですか、それとも再入可能ではないためですか?
printf()が再入可能でない場合、何らかの方法で「同期」されていない限り、マルチスレッドプログラムにも使用できないことを意味しませんか?
ありがとう、
それらすべて、そしてそれ以上かもしれないと思います。一般的なprintf()
実装では、動的(ヒープ)メモリ割り当てを実行できますが、これは通常、実行するのが最速ではなく、再入可能でないという問題もある可能性があります。通常、割り込みサービスルーチンに多くの時間を費やすことは想定されていないため、堅牢性が重要になる可能性があります。
およびについての議論については、この回答を参照してください。printf()
malloc()
再入可能でもスレッドセーフでもないため、ISR に含めるべきではありませんが、主に、ISR から呼び出すとプログラム全体がロックされ、極端な割り込みジッターが発生し、即座にエラーが発生する非常に巨大な関数であるためです。プログラムのリアルタイム パフォーマンスのすべてのヒントを殺します。
スレッドセーフかどうかに関係なく、大げさな関数を ISR に含めるべきではありません。
カーネルの割り込みハンドラーには通常、はるかに特別な制限がありますが、割り込みを意味していると想定します。同じ引数がシグナル ハンドラーに適用されますが、通常は割り込みハンドラーの特別な制限よりも単純です。私の仮定が間違っている場合は、答えの「割り込み」を「信号」に置き換えるだけで適用されます。
関数は、シグナル/割り込みセーフではなく、スレッドセーフにすることができます。関数がロックで内部状態を保護し、割り込みを取得するときにそのロックを保持する場合、ロックを保持する実行パスが割り込みによってブロックされるため、割り込みハンドラーがそのロックを取得する方法はありません。ロックを解放するには、割り込みハンドラーを終了し、ロックが解放されるまでスレッドの実行を再開してから、割り込みハンドラーに戻る必要があります。これは通常、カーネルがロックを待っているときに実行を生成できるスレッドとして割り込みハンドラーを実装していない限り、実際には実行できません。
関数を割り込みとスレッドセーフの両方にする通常の方法は、ロックを保持しながら割り込みをブロックすることですが、これは非常に高価であり、非常に必要でない限り行われません。
Cのprintf()はISRでは使用されないはずだと聞きました。それはブロッキング呼び出しであるためですか、それとも再入可能ではないためですか?
より正確にprintf()
は、は非同期信号に対して安全な関数ではないためです。SignalConceptsの下部にあるasync-signal-safeのリストを参照してください。
そこから printf() を呼び出すと、おそらく 1 回か 2 回うまく機能する可能性があります。ブロックしようとすると、割り込みハンドラにはスレッド コンテキストがないため、ほとんど惨事になります。
組み込みのものにマルチスレッド ライブラリをリンクすると、printf() はミューテックス スタイルのロックを取得して、複数のスレッドから安全に呼び出すことができます。
他のポスターが言うように、割り込みハンドラからそのようなものを呼び出さないでください。シグナリング セマフォ ユニットは常に安全です、IME。OSドキュメントで特に明記されている場合にのみ、その他のもの。