web-dev-qa-db-ja.com

`EINTR`:その背後に根拠はありますか?

背景としての小さな話

EINTRは、いわゆる割り込み可能なシステムコールが返すエラーです。システムコールの実行中にシグナルが発生した場合、そのシグナルは無視されず、シグナルハンドラが SA_RESTART 設定されておらず、このハンドラーがそのシグナルを処理する場合、システムコールはEINTRエラーコードを返します。

補足として、Pythonでncursesを使用すると、このエラーが頻繁に発生しました。

質問

POSIX標準で指定されているこの動作の背後にある根拠はありますか? (カーネルの設計によっては)再開できない場合があることは理解できますが、カーネルレベルで自動的に再起動しない理由は何ですか?これはレガシーまたは技術的な理由によるものですか?これが技術的な理由によるものである場合、これらの理由は現在も有効ですか?これがレガシーの理由である場合、歴史は何ですか?

8
Hibou57

プログラムの残りの部分は不明な状態であるため、シグナルハンドラで重要なことを行うのは困難です。ほとんどのシグナルハンドラーはフラグを設定するだけです。フラグは後でチェックされ、プログラムの他の場所で処理されます。

システムコールを自動的に再開しない理由:

ブロッキングと割り込みなしrecv() システムコールによってソケットからデータを受信するアプリケーションを想像してください。私たちのシナリオでは、データが非常に遅くなり、プログラムはそのシステムコールに長く存在します。そのプログラムには、フラグを設定するSIGINTのシグナルハンドラーがあり(これは他の場所で評価されます)、システムコールが自動的に再起動するように_SA_RESTART_が設定されます。プログラムがrecv()にあり、データを待機しているとします。しかし、データは到着しません。システムコールがブロックします。プログラムは今キャッチ ctrl-c ユーザーから。システムコールが中断され、フラグを設定するだけのシグナルハンドラが実行されます。次に、recv()が再起動され、まだデータを待機しています。イベントループがrecv()でスタックし、フラグを評価してプログラムを正常に終了する機会がありません。

_SA_RESTART_が設定されていない場合:

上記のシナリオでは、_SA_RESTART_が設定されていない場合、recv()は再起動されずにEINTRを受け取ります。システムコールは終了し、続行できます。もちろん、プログラムは(できるだけ早く)フラグ(シグナルハンドラーによって設定された)をチェックし、クリーンアップなどを行う必要があります。

12
chaos

Richard Gabrielが論文を書きました The Rise of 'Worse is Better' これは、Unixでの設計の選択について説明しています。

MITとBerkeley(Unixで作業中)の2人の有名な人が、オペレーティングシステムの問題について話し合うためにかつて会いました。MITの人は、 ITS(MIT AI Labオペレーティングシステム)であり、Unixソースを読んでいました。彼は、UnixがPCの敗者問題をどのように解決したかに興味を持っていました。PCの敗者問題は、ユーザーがプログラムはシステムルーチンを呼び出して、IO buffersなど)の重大な状態になる可能性のある長い操作を実行します。操作中に割り込みが発生した場合、ユーザープログラムの状態を保存する必要があります。システムルーチンの呼び出しは通常単一の命令であり、ユーザープログラムのPCはプロセスの状態を適切にキャプチャしません。システムルーチンは、バックアウトするか押し進める必要があります。正しいのは、ユーザープログラムをバックアウトして復元することですシステムルーチンを呼び出した命令へのPCにより、割り込み後のユーザープログラムの再開など、システムルーチンに再び入ります。 PCがPC loser-ingに強制変換されているため、これはloser modeと呼ばれます。ここで、「loser」はMITの「ユーザー」の愛称です。

MIT男は、このケースを処理するコードをまったく見ず、ニュージャージーの男に問題の処理方法を尋ねました。ニュージャージーの男は、Unixの人々は問題を認識していると言いましたが、解決策は、システムルーチンが常に終了することでしたが、システムルーチンがそのアクションを完了できなかったことを示すエラーコードが返される場合がありました。次に、正しいユーザープログラムがエラーコードをチェックして、単純に試行するかどうかを判断する必要がありました。 MIT=男はこの解決策が適切ではなかったので、嫌いでした。

ニュージャージー州の男は、Unixの設計哲学はシンプルであり、正しいことは複雑すぎるため、Unixのソリューションは正しいと述べました。さらに、プログラマーはこの追加のテストとループを簡単に挿入できます。 MITの人は、実装は単純であるが機能へのインターフェースは複雑であると指摘しました。ニュージャージーの人は、正しいトレードオフがUnixで選択されていると言いました。つまり、実装の単純さがより重要でした。インターフェースの単純さよりも。

4
Brad Schoening