我々は、これが非同期printf
信号安全機能ではないことを知っています。以下は私の基本的な理解です。
printf
inメソッドを呼び出してmain
内容がstdioバッファに書き込まれたと仮定すると、バッファがファイルにフラッシュされる直前にシグナルが到着し、シグナルハンドラも呼び出されますprintf
。 2 番目のハンドラはprintf
その内容をバッファに追加し、buffer の最初の呼び出しと 2 番目の呼び出しの内容が一致しないため無効なので、シグナル ハンドラで非同期でない安全関数を使用することはできません。私の理解は正しいですか?
私の理解が正確であれば、非同期安全機能はこの問題をどのように解決しますか?安全な関数はまだ呼び出しのための貴重なバッファデータを含むことができるバッファを処理する必要があるため?
答え1
printf
説明したように、同期せずにグローバル状態を操作するため、非同期信号は安全です。楽しみを加えるために再入口は必要ありません。あなたの例では、シグナルはprintf
最初のランタイムによって処理される可能性がありますが、2番目のシグナルは最初の呼び出しの状態を台無しにする可能性がありますprintf
。
非同期信号を安全に使用するための推奨される方法は、シグナルハンドラがどこかにフラグを設定し、基本プログラムフローにフラグを処理させることです。これは、再入、直列化された出力の問題を防ぎ、信号ハンドラをすばやく維持するのに役立ちます。
答え2
私の理解は正しいですか?
最大。バッファオフセットとサイズを変更すると、ネストされたprintf呼び出しが互いに重複してデータが一貫していないだけでなく、競合が発生する可能性があるという問題もあります。
非同期安全機能はこの問題をどのように解決しますか?
2種類あります非同期信号安全機能:
strlen(3)などの再入関数は、ローカル変数、パラメータ、および戻り値を保持するために使用されるメモリ以外のメモリを変更しません。
関数はkill(2)、waitpid(2)などの単純なシステムコールラッパーです。上記のように、userland部分は完全に再入可能ですが、カーネル部分の場合、カーネルはすべてを処理します。