背景としての雑談
EINTR
いわゆる割り込み可能なシステムコールによって返される可能性があるエラーです。システムコールの実行中にシグナルが発生した場合、そのシグナルは無視されません。信号ハンドラが定義されているが存在しない場合SA_RESTART
設定され、このハンドラが信号を処理すると、システムコールはEINTR
エラーコードを返します。
ちなみに、Pythonで使用すると、このエラーが頻繁に発生しますncurses
。
質問
POSIX規格で指定されているこの動作の背後にはどのような理由がありますか? (カーネル設計によって)回復されない可能性があることを理解できますが、カーネルレベルで自動的に再起動しないのはなぜですか?これは従来の理由ですか、それとも技術的な理由ですか?これが技術的な理由であれば、その理由は今でもまだ有効ですか?これが遺産上の理由なら、その歴史はどうなりますか?
答え1
プログラムの残りの部分は不明な状態にあるため、信号ハンドラで重要な作業を実行するのは困難です。ほとんどのシグナルハンドラは、後でプログラムの他の場所で確認して処理するフラグを設定します。
システムコールが自動的に再開されない理由:
ソケットからデータを受け取るアプリケーションを想像してください。ブロックして中断できない recv()
システムコール。私たちのシナリオでは、データ転送は非常に遅く、プログラムは長い間このシステムコールに常駐しています。プログラムにはSIGINT
、フラグ(他の場所で評価)を設定し、SA_RESTART
自動的に再起動するようにシステムコールを設定するシグナルハンドラがあります。プログラムがrecv()
データを待っていると想像してください。しかし、データは到着しません。システムコールのブロック。これでプログラムはユーザーからキャプチャしますctrl。cシステムコールが中断され、フラグを設定したシグナルハンドラが実行されます。その後、recv()
再起動し、まだデータを待っています。recv()
フラグを評価し、プログラムを正常に終了する機会なしにイベントループが中断されます。
設定されていない場合SA_RESTART
:
上記のシナリオでSA_RESTART
設定しないと、再起動するのではなくrecv()
受信されます。EINTR
続行できるように、システムコールが終了します。もちろん、プログラムは(できるだけ早く)フラグ(信号ハンドラによって設定されている)を確認して整理する必要があります。
答え2
Richard Gabrielが論文を書いた。「悪いほど良い」という認識の増加Unixのデザイン選択について説明します。
MIT出身とバークレー出身(しかしUnixで働いている)という2人の著名な人々がかつて出会い、オペレーティングシステムの問題を議論しました。 MIT出身のこの人はITS(MIT Artificial Intelligence Laboratory Operating System)についてよく知っており、Unixのソースコードも読んでいました。彼はUnixがPCエラーの問題をどのように解決したかに興味がありました。 PC損失の問題は、ユーザープログラムが重要な状態(IOバッファなど)がある可能性がある長い操作を実行するためにシステムルーチンを呼び出すときに発生します。操作中に中断が発生した場合は、ユーザープログラムの状態を保存する必要があります。システムルーチンへの呼び出しは通常単一のコマンドであるため、ユーザープログラムのPCはプロセスステータスを適切にキャプチャできません。システムルーチンは終了または進行する必要があります。正しいアプローチは、システムルーチンを呼び出すコマンドでユーザープログラムPCをシャットダウンして復元し、システムルーチンに戻るなどの中断後にユーザープログラムを再開できるようにすることです。
PC loser-ing
PCが強制的に実行されるため、そう呼ばれますloser mode
。ここで「敗者」とは、「ユーザー」を指すMITの愛情用語です。MITにいる人はこの事件を処理するコードを見ていないし、ニュージャージーの人に問題を処理する方法を尋ねました。ニュージャージー州の従業員はUnixの人々が問題を知っていますが、解決策は常にシステムルーチンを完了させることでしたが、システムルーチンが操作を完了できなかったことを示すエラーコードを返すことが時々ありました。その後、正しいユーザープログラムはエラーコードを確認して、システムルーチンを再試行するかどうかを判断する必要があります。 MITの人々は、この解決策が正しくないので好きではありませんでした。
ニュージャージー州の人々は、Unixソリューションが正しいソリューションだと言います。なぜなら、Unixは単純に設計されており、正しいことは複雑すぎるからです。さらに、プログラマはこれらの追加のテストとループを簡単に挿入できます。 MITの人々は、実装は簡単ですが、機能へのインターフェースは複雑であると指摘しました。ニュージャージー人は、Unixでは正しいトレードオフが選択されると言います。つまり、実装のシンプルさがインターフェイスのシンプルさよりも重要であると言いました。