73

シグナルハンドラに引数を提供/渡すことはできますか?

/* Signal handling */
struct sigaction act;
act.sa_handler = signal_handler;
/* some more settings */

ハンドラーは次のようになります。

void signal_handler(int signo) {
    /* some code */
}

何か特別なことをしたい場合、つまり一時ファイルを削除したい場合、それらのファイルを引数としてこのハンドラに渡すことはできますか?

編集 0: 回答ありがとうございます。私たちは通常、グローバル変数の使用を回避/推奨しません。この場合、巨大なプログラムがあると、さまざまな場所で問題が発生する可能性があり、多くのクリーンアップを行う必要がある場合があります。API がこのように設計されたのはなぜですか?

4

7 に答える 7

66

独自のデータをパラメーターとしてシグナル ハンドラーに渡すことはできません。代わりに、パラメーターをグローバル変数に保存する必要があります。(そして、シグナルハンドラをインストールした後にこれらのデータを変更する必要がある場合は、本当に、本当に注意してください)。

編集 0 への応答:歴史的な理由。シグナルは非常に古く、非常に低レベルの設計です。基本的には、カーネルにマシンコードへの単一のアドレスを与え、そのようなことが起こった場合にこの特定のアドレスに移動するように要求するだけです。ここでは、カーネルが飾り気のないベースライン サービスを提供し、ユーザー プロセスがそれ自体に対して合理的に期待できることは何でも、それ自体で実行する必要がある「ポータブル アセンブラー」の考え方に戻ります。

また、グローバル変数に対する通常の引数は、ここでは実際には適用されません。シグナルハンドラー自体はグローバル設定であるため、ユーザー指定のパラメーターのいくつかの異なるセットを持つ可能性はありません。(まあ、実際には完全にグローバルではなく、スレッドグローバルのみです。しかし、スレッド化 API には、スレッドローカルストレージのメカニズムが含まれています。これは、この場合に必要なものです)。

于 2011-08-07T02:00:14.477 に答える
18

シグナル ハンドラーの登録は、既にグローバル変数と同等のグローバル状態です。したがって、グローバル変数を使用して引数を渡すことはそれほど問題ではありません。ただし、とにかくシグナルハンドラから何かを行うのは大きな間違いです (専門家でない限り、ほぼ確実に未定義の動作です!)。代わりにシグナルをブロックし、メイン プログラム ループからシグナルをポーリングするだけで、これらの問題をすべて回避できます。

于 2011-08-07T02:49:49.627 に答える
1

ファイルの名前をグローバル変数に格納し、ハンドラーからアクセスします。シグナル ハンドラー コールバックには、問題を引き起こした実際のシグナルの ID (例: SIGINT、SIGTSTP) という 1 つの引数のみが渡されます。

編集 0:「ハンドラーへの引数を許可しないのには、確固たる理由があるに違いありません。」<-- 割り込みベクトルがあります (基本的に、考えられる各シグナルのルーチンへのジャンプ アドレスのセット)。割り込みベクトルに基づいて、割り込みがトリガーされる方法を考えると、特定の関数が呼び出されます。残念ながら、変数に関連付けられたメモリがどこで呼び出されるかは明確ではなく、割り込みによってはメモリが実際に破損する可能性があります。これを回避する方法はありますが、既存の int 0x80 アセンブリ命令 (一部のシステムではまだ使用されています) を利用することはできません。

于 2011-08-07T02:02:48.533 に答える
0

クラスのメソッドであるシグナルハンドラを使用できます。その後、そのハンドラーはそのクラスのメンバー データにアクセスできます。C signal() 呼び出しの周りで Python がカバーの下で何をしているのか完全にはわかりませんが、データのスコープを変更しているに違いありません。

これが機能することに驚きましたが、機能します。これを実行してから、別の端末からプロセスを強制終了します。

import os, signal, time

class someclass:
    def __init__(self):
        self.myvalue = "something initialized not globally defined"
        signal.signal(signal.SIGTERM, self.myHandler)
    def myHandler(self, s, f):
        # WTF u can do this?
        print "HEY I CAUGHT IT, AND CHECK THIS OUT", self.myvalue


print "Making an object"
a = someclass()

while 1:
    print "sleeping.  Kill me now."
    time.sleep(60)
于 2012-04-25T15:43:41.237 に答える