プロセスA内のスレッドがprintfを呼び出しており、別のスレッド がシグナルを受信した後、printfを呼び出したとします。これはおそらく カーネルが何をするか分からないからです。 2つの呼び出しを区別することができないからです。
問題が発生するのはカーネルではありません。それはあなた自身のアプリケーションです。 printf
はカーネル関数ではありません。これは、アプリケーションが使用するCライブラリの関数です。 printf
は、実際にはかなり複雑な機能です。さまざまな出力フォーマットをサポートしています。
この形式の最終結果は、標準出力に書き出される書式付き出力文字列です。そのプロセス自体にもいくつかの作業が必要です。フォーマットされた出力文字列は、内部のstdout
ファイルハンドルの出力バッファに書き込まれます。特定の定義された条件が発生したとき、すなわち出力バッファがいっぱいであるとき、および/または改行文字が書き込まれるときにはいつでも、出力バッファはフラッシュされます(カーネルは引き継いで、定義されたデータのまとまりをファイルに書き込みます)。出力ストリーム。
これらはすべて出力バッファの内部データ構造でサポートされています。これは、Cライブラリのジョブなので、気にする必要はありません。今、信号はprintf
が動作している間はどの時点でも到達することができます。そして、いつでも、私は意味します。 printf
が出力バッファの内部データ構造の更新途中で非常にうまく到着する可能性があり、printf
がまだ更新を完了していないため一時的に不整合な状態になっています。
例:現代のC/C++実装では、printf
はシグナルセーフではないかもしれませんが、スレッドセーフです。複数のスレッドはprintf
を使用して標準出力に書き込むことができます。最終的な出力が実際に意味をなさないことを確かめるために、このプロセスを自分自身で調整するのはスレッドの責任です。複数のスレッドの出力からランダムに混乱することはありませんが、それはその点です。
重要な点は、printf
はスレッドセーフであり、通常はどこかにプロセスに含まれるmutexがあることを意味します。したがって、発生する可能性のあるイベントのシーケンスは次のとおりです。
ここで、mutex
はロックされています。シグナルハンドラについては、プロセス内のどのスレッドがシグナルを処理するのかは一般的には指定されていません。与えられた実装はランダムにスレッドを選ぶかもしれませんし、常に現在実行中のスレッドを選ぶかもしれません。いずれにしても、信号を処理するためにここにprintf
をロックしたスレッドを確実に選択することができます。
これでシグナルハンドラが実行され、printf
を呼び出すことになりました。 printf
の内部ミューテックスがロックされているため、スレッドはミューテックスがロック解除されるのを待たなければなりません。
お待ちください。
お待ちください。
あなたが物事を追跡していたならば、シグナルを処理するために中断されたスレッドによってミューテックスがロックされるからです。スレッドが実行を再開するまで、mutexはロック解除されません。しかし、シグナルハンドラが終了してスレッドが実行を再開するまでは起こりませんが、シグナルハンドラはmutexがロック解除されるのを待っています。
あなたは骨が折れています。
printf
は、この問題を回避するために、std::recursive_mutex
のC++に相当するものを使用することがありますが、シグナルによって導入される可能性のあるデッドロックをすべて解決するわけではありません。
要約すると、「信号を受信してその信号ハンドラ内から非同期セーフ機能を呼び出すことが安全でない」理由は、それが定義上ではないためです。シグナルが非同期イベントであり、非同期セーフな関数ではないので、定義上、それはできません。水は水であるため濡れていますが、
短い形式は、「標準がそう言っているから」または「あなたのライブラリがそう言っているから」という形式です。長い形式は、コードが書かれていないことです非同期アクセス機能:非同期処理のほとんどの方法は、同期実行時にコストがかかるため、非同期処理関数を使用するとパフォーマンスがよく感じられます。 – Yakk
ありがとう私は非同期非安全関数をパラレルに呼び出すのではなく、返されないシグナルハンドラのコンテキスト内で呼び出すような方法でコードを構造化するといいですか? – Curious
'malloc'固有のバージョン:https://stackoverflow.com/questions/3366307/why-is-malloc-not-async-signal-safe –