2

「「fgets」を書き直してアラームを含め、5秒後にユーザーがデータを入力しなかった場合、「fgets」がNULLへのポインターを返すようにします(タイムアウト)」

大規模な宿題のこの1つの問題であり、信号、キャッチ、処理などを調べ始めたばかりです。そうは言っても、本と講義のスライドにはこれが欠けています...

このタイプの例外をキャッチするハンドラーを作成することを思いつき、アラームがどのように機能するかは理解していますが、インターフェイスがどのように機能するかはわかりません。

今「fgets」について考えているだけです...他のすべての作業が行われる前に(リターンポインタの直前に)アラームを入れるだけの場合:

char *fgets(//...//)
{
    alarm(5);
    char * to_return = NULL;
    //...//

ユーザーがデータを入力する前にアラームが鳴った場合、ハンドラーは単に「NULLを返す」ことができますか?ハンドラーが完了した後、実行は「fgets」内に戻りませんか?ハンドラーが関数内で実行できること(つまり、関数に値を返すように強制すること、関数内で宣言されている変数を変更すること、別の関数呼び出しにジャンプさせること)に混乱していると思います。等。)

4

1 に答える 1

1

まず、シグナル ハンドラーは実行の個別のスレッドです。シグナルが発生すると、コードの「通常の」実行が中断され、シグナル ハンドラが実行されます。ハンドラが戻ると、中断された時点からコードの実行が再開されます。

したがって、1) シグナル ハンドラーはfgets()(少なくとも直接ではなく) からの戻り値に影響を与えることができず、2) 値を返すこともできません。(シグナル ハンドラーをインストールする関数は、パラメーターとして整数を受け取り、戻り値の型を持つsignal()関数へのポインターを要求することに注意してください。void

シグナルハンドラができることは、値を設定することです。標準(C99、「シグナル処理」の章、7.14.1.1(5))はこれについて次のように述べています。

abortまたは関数の呼び出しの結果以外でシグナルが発生したraise場合、シグナル ハンドラーが として宣言されたオブジェクトに値を代入する以外の静的ストレージ期間を持つオブジェクトを参照する場合volatile sig_atomic_t、またはシグナル ハンドラーが任意の関数を呼び出す場合、動作は未定義です。abort 関数、_Exit関数、またはsignalハンドラの呼び出しの原因となったシグナルに対応するシグナル番号に等しい最初の引数を持つ関数以外の標準ライブラリ内。

volatile sig_atomic_tこれが意味することは、あなたとあなたのシグナルハンドラーの両方fgets()がそれを「見る」ことができる型の変数を宣言し、それをデフォルト値に初期化し、シグナルハンドラーにその値を変更さfgets()せて、シグナルが発火したことを確認できるということです。

もちろん、fgets()ユーザーが何かを入力するまで待機すると、シグナルが発生した後でも待機します...それをどのように解決するかは、入力をどのように行うかの問題です。getch()(ISO / ANSI Cではない)のような入力にノンブロッキングチェックを使用するか、read()そのR.の動作に依存するか(これは、下のPOSIXレイヤーに依存していますfgets())、または何か他のものに依存します。これを行うための厳密な ISO/ANSI C の方法については考えられないため、コースで既に学んだことや行ったことに依存します。

ああ、勇気があるなら、標準関数を別の動作に再定義するのは本当に悪い考えだとインストラクターに伝えてください(彼を「ばか」と呼ぶのを避けるため)。fgets()ではない が必要な場合はfgets()、別の名前を付けfgets_timed()ます。

于 2012-06-06T07:46:50.750 に答える