システムコールを再開しても安全ですか?

システムコールを再開しても安全ですか?

割り込み時にシステムコールを処理する方法を説明する教科書を読んでいます。

システムコールが中断される可能性があります。長い間プロセスをブロックすることができる読み取り、待機、承認などのシステムコールは、遅いシステムコールと呼ばれます。一部の以前のバージョンのUnixでは、ハンドラがシグナルをキャッチしている間に中断された遅いシステムコールはシグナルハンドラが返されたときに再開されず、エラー条件とerrnoがEINTRに設定されたユーザーにすぐに返されます。このようなシステムでは、プログラマーは中断されたシステム呼び出しを手動で再開するコードを含める必要があります。

しかし、システムコールを再開することは常に安全ですか?システムコールが完了する前にリセットする必要がある内部データ構造をシステムコールが保持しているとします。したがって、長期実行およびブロックシステムコールを開始し、シグナルがそれを中断するとシステムコールが再開されるため、最初のシステムコールではデータ構造をリセットする機会はありません。

以前の呼び出しのデータ構造がリセットされていないため、2番目のシステム呼び出しが発生した後にデータ構造が一致しないため、操作が破損する可能性があります。

もしそうなら、システムコールを再開するのは安全ですか?

答え1

Linuxではそうです。リターンシステムコールを再開することは常に安全ですEINTR。戻り値は、有用な進行が行われる前にシステムコールが中断されたため、再起動する必要があることを意味します。システムコールはこれを念頭に置いて実装されます。

システムコール割り込みによるシステム状態の変更は、異なって処理されます。read中断される前に一部のデータを取得する呼び出しは、そのデータを返すことで成功を示します。write中断される前に一部のデータを送信した呼び出しは、自分が書き込んだデータの量を返します。これも成功を示します。 (ちなみに、成功した呼び出しが要求した操作をすべて実行したと仮定するのではなく、これらの関数の戻り値を確認する必要がある理由の1つです。)

SA_RESTART適切な信号にフラグを設定すると、多くのシステムコールが自動的に再開される可能性があります。 GNU Cライブラリは、再起動コードを書くのに役立つマクロを提供します。TEMP_FAILURE_RETRY存在するunistd.h_GNU_SOURCEすでに定義されている場合は定義)。

EINTRLinuxでは、シグナルハンドラがなくてもシステムコールが返されることがあります。

「シグナルハンドラ割り込みシステムコールおよびライブラリ関数」セクションman 7 signalさまざまなシナリオで影響を受けるシステムコールのリストを含むすべての詳細が含まれています。

関連情報