13
#include<stdio.h>
#include<signal.h>

void handler(int signo)
{
    printf("Into handler\n");
    while(1);
}
int main()
{
    struct sigaction act;
    act.sa_handler = handler;
    act.sa_flags = 0;
    sigemptyset(& act.sa_mask);
    sigaction(SIGINT, &act, NULL);
    while(1);
    return 0;
}

KeyboardInterruptを一度キャッチした後、もう一度「Ctrl+C」を押すと、SIGINT が処理されません... 「Ctrl+C」を押すたびに「Into handler」が出力されるようにするつもりです。

「SIGINT handler()」自体の中で SIGINT をキャッチしたい..

4

5 に答える 5

12

現在処理している信号と同じ信号をキャッチするには、sa_maskにSA_NODEFERを設定する必要があります。

SA_NODEFER:独自のシグナルハンドラー内からシグナルを受信することを妨げないでください。SA_NOMASKは、このフラグの廃止された非標準の同義語です。

于 2010-03-10T17:15:41.077 に答える
8

ただし、あなたがしていることは非常に悪い考えのように思えます。単にハンドラーからフラグを設定してそこから戻り、メインから印刷を行う方が良いかもしれません。

シグナル ハンドラー自体でシグナルを設定するSA_NODEFERか、再度有効にする必要があります。そうしないと、シグナルがブロックされるか、ハンドラーの呼び出しの直前にデフォルトの動作に戻されます。

printfシグナル ハンドラからの呼び出しは未定義の動作です。プログラムがクラッシュする可能性があります。実際にシグナル ハンドラから安全に呼び出すことができる関数のリストは非常に限られています。glibc の Async-Signal-Safe 関数のリストが必要です

于 2010-03-10T17:05:33.723 に答える
3

printfシグナルハンドラー内で関数を使用すると、未定義の動作が発生する可能性があるため、使用することはお勧めできませんコードサンプルには、シグナルハンドラーが機能するための重要なビットがありません。これについては、 Q6のブログをご覧ください。セグメンテーション違反をトラップする方法は?'

また、シグナルハンドラーのテスト中にプログラムを終了する方法として、ループをより堅牢なものに置き換える必要がありwhileます...どのように終了しますか?

于 2010-03-10T17:17:49.647 に答える
2

printf の代わりに次のようなものを使用できます。

const char *str = "Into handler\n";
write(1, str, strlen(str));

この関数write(..)は、シグナル ハンドラから安全に呼び出されます。unistd.hヘッダーを含めることを忘れないでください。

于 2014-12-19T10:31:54.627 に答える
1

ハンドラーの "while(1)" により、最初のサービス コールが返されなくなります。それを削除すると、後続の割り込みにより、ハンドラーが再度呼び出されるようになります。

割り込みサービス ルーチンは、呼び出し元のスレッドが戻るのを妨げてはなりません。

于 2010-03-10T17:02:00.157 に答える