これが現在の問題です。私は2つの異なるプログラムを作成しました(1つは他のプログラムを管理し、もう1つは複数回実行されます)。プログラムは信号を介してやり取りします。私の質問は、シグナルを送信するプログラムのプロセス ID を取得することは可能ですか (およびその方法) です。私のプログラムでは、signal() を使用してシグナルをキャッチし、kill() を使用してシグナルを送信します。
4 に答える
signal() は標準 C ライブラリにありますが、この関数は移植性がなく、その動作はシステムに依存します。POSIX.1 である sigaction() を使用することをお勧めします。
ハンドラー void h(int sig) で sigaction を使用する方法の例を次に示します。
int mysignal (int sig, void (*h)(int), int options)
{
int r;
struct sigaction s;
s.sa_handler = h;
sigemptyset (&s.sa_mask);
s.sa_flags = options;
r = sigaction (sig, &s, NULL);
if (r < 0) perror (__func__);
return r;
}
オプションについては man sigaction で説明されています。良い選択はoptions=SA_RESTART
です。
シグナルを送信したプロセスの PID を知るには、 を設定し、 の代わりにコールバックoptions=SA_SIGINFO
を使用します。フィールドを持つ構造体を受け取ります。を使用してデータを信号に関連付けることができます。sa_sigaction
sa_handler
siginfo_t
si_pid
sigqueue
一般的に言えば、安全な方法で通信するためにシグナルを使用することは悪い考えです (n シグナルが送信されると、最初のシグナルのみが配信される可能性があります。他のデータを関連付けるフックはありません。利用可能なユーザーシグナルは 2 つだけです)。 . パイプ、名前付きパイプ、またはソケットを使用することをお勧めします。
シグナルを送信しているプロセスのプロセス ID を取得するには、オプション SA_SIGINFO に含める必要があります。その場合、sigaction へのインターフェースはわずかに異なります。使用する適切なハンドラーとその設定方法の例を次に示します。(SA_RESTART は一般的には良い考えなので、オプションとして含めていますが、必須ではありません)
// example of a handler which checks the signalling pid
void handler(int sig, siginfo_t* info, void* vp) {
if (info->si_pid != getpid()) {
// not from me (or my call to alarm)
return;
}
// from me. let me know alarm when off
alarmWentOff = 1;
}
ハンドラーを設定するための私の一般的なコードは次のとおりです。
typedef void InfoHandler(int, siginfo_t *, void *);
InfoHandler*
SignalWithInfo(int signum, InfoHandler* handler)
{
struct sigaction action, old_action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_sigaction = handler;
sigemptyset(&action.sa_mask); /* block sigs of type being handled */
action.sa_flags = SA_RESTART|SA_SIGINFO; /* restart syscalls if possible */
if (sigaction(signum, &action, &old_action) < 0)
perror("Signal error");
return (old_action.sa_sigaction);
}
最後に、この特定のケースでは:
SignalWithInfo(SIGALRM, handler);