4

私は自分の問題の解決策を長い間探していたので、あなたに頼っています:

次のコードを検討してください。

static char done = 0;
static void sigHandler(void)
{
    done = 1;
}

int user_input()
{
    return (getchar() == 'q') ? 0 : 1;
}

int main(void)
{
    signal(SIGTERM, sigHandler);
    signal(SIGINT, sigHandler);
    while (user_input() != 0 && !done)
        usleep(1000);
    printf("exiting\n");
    return 0;
}

予想される動作: ユーザーが q を入力して Enter すると、プログラムは終了します。CTRL+が押されるとC、フラグ「done」を 1 に設定してプログラムを終了する sigHandler 関数によって捕捉されます。

観察された動作: CTRL+C文字は getchar() 呼び出しによって食べられ、sigHandler 関数は実行されません。CTRL+をC押してから Enter を押すと、sigHandler 関数が呼び出され、プログラムが終了します。

より多くの経験と知識を持っている人が私を助けてくれますか?

ご意見ありがとうございます:)

4

3 に答える 3

6

コードは実際には期待どおりに機能していますdone。 から戻るまでフラグをテストしていないためuser_input()、control-C の後に追加の文字を入力する必要があります。

control-C を取得したときに への呼び出しを中止したい場合は、おそらく/getcharを使用するなど、何か醜いことをしなければならないでしょう。setjmplongjmp

于 2011-11-02T09:51:17.267 に答える
6

醜いハックに頼らずに通話を中止する方法があります (Paul R が言ったことに反して)。の代わりにset toを使用する必要がsigaction()あります。sa_flags0signal()

さらに、signal(2) のマニュアルには次のように書かれています。

その使用を避けてください:代わりにsigaction (2) を使用してください。

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

static char done = 0;
static void sigHandler(int signum)
{
    done = 1;
}

int user_input()
{
    return (getchar() == 'q') ? 0 : 1;
}

int main(void)
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = sigHandler;
    sa.sa_flags = 0;// not SA_RESTART!;

    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    while (user_input() != 0 && !done)
        usleep(1000);
    printf("exiting\n");
    return 0;
}

通常、シグナルをキャッチして処理した後、ほとんどの (すべてではないかどうかはわかりません) syscall が再起動されます。このようにして、sigint シグナルを処理した後、getchar 関数は何も起こらなかったかのように続行します。で sigaction を呼び出すことにより、この動作を変更できますsa_flags=0

このように、SIGINTを処理した後、getchar戻り-1、errnoが「中断されたシステムコール」に設定されます(定数名は今覚えていません)。

また、-1 を返す場合を処理するように user_input() 関数を書き直す必要があります。

于 2011-11-02T19:18:52.327 に答える
6

Ctrl-C 文字はgetchar()呼び出しによって食べられ、sigHandler 関数は決して実行されません。

Ctrl-C は に食べられませんgetchar。その結果、シグナルが配信されsigHandlerて実行されます。これが設定doneされて返されます。そのときだけgetchar呼び出され、改行が取り込まれ、その後doneチェックされてプログラムが終了します。

ところで、シグナルハンドラはintではなく引数を取りますvoid

于 2011-11-02T09:51:52.873 に答える