また、プログラムでシグナル送信者を特定する必要があったため、grawity の回答を使用して、プログラムで使用しました。
サンプル コードは次のとおりです。
send_signal_raise.c
// send signal to self test - raise()
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
static int int_count = 0, max_int = 5;
static struct sigaction siga;
static void multi_handler(int sig, siginfo_t *siginfo, void *context) {
// get pid of sender,
pid_t sender_pid = siginfo->si_pid;
if(sig == SIGINT) {
int_count++;
printf("INT(%d), from [%d]\n", int_count, (int)sender_pid);
return;
} else if(sig == SIGQUIT) {
printf("Quit, bye, from [%d]\n", (int)sender_pid);
exit(0);
}
return;
}
int raise_test() {
// print pid
printf("process [%d] started.\n", (int)getpid());
// prepare sigaction
siga.sa_sigaction = *multi_handler;
siga.sa_flags |= SA_SIGINFO; // get detail info
// change signal action,
if(sigaction(SIGINT, &siga, NULL) != 0) {
printf("error sigaction()");
return errno;
}
if(sigaction(SIGQUIT, &siga, NULL) != 0) {
printf("error sigaction()");
return errno;
}
// use "ctrl + c" to send SIGINT, and "ctrl + \" to send SIGQUIT,
int sig;
while(1) {
if(int_count < max_int) {
sig = SIGINT;
} else {
sig = SIGQUIT;
}
raise(sig); // send signal to itself,
sleep(1); // sleep a while, note that: SIGINT will interrupt this, and make program wake up,
}
return 0;
}
int main(int argc, char *argv[]) {
raise_test();
return 0;
}
コンパイル:
gcc -pthread -Wall send_signal_raise.c
実行:
./a.out
機能:
プログラムは SIGINT
を送信します SIGQUIT
を送信する前に、自分自身に 10 回
また、実行中に CTRL を押します +C SIGINT
を送信する 、または CTRL +\ SIGQUIT
を送信する これにより、プログラムが手動で終了します。
プログラムは、シグナルの送信者を特定できました。
BCC には killsnoop
が含まれます 効用。 BPF をサポートするカーネルが必要です。
killsnoop (8) マンページからの抜粋:
killsnoop traces the kill() syscall, to show signals sent via this method. This may be
useful to troubleshoot failing applications, where an unknown mechanism is sending
signals.
This works by tracing the kernel sys_kill() function using dynamic tracing, and will need
updating to match any changes to this function.
This makes use of a Linux 4.5 feature (bpf_perf_event_output()); for kernels older than
4.5, see the version under tools/old, which uses an older mechanism.
Since this uses BPF, only the root user can use this tool.
2 つの Linux 固有の方法は SA_SIGINFO
です と signalfd()
、これにより、プログラムは very を受け取ることができます 送信者の PID を含む、送信されたシグナルに関する詳細情報。
-
sigaction()
に電話する それにstruct sigaction
を渡しますsa_sigaction
に目的のシグナル ハンドラがある そしてSA_SIGINFO
sa_flags
のフラグ 設定。このフラグを使用すると、シグナル ハンドラは 3 を受け取ります 引数、そのうちの 1 つはsiginfo_t
です 送信者の PID と UID を含む構造。 -
signalfd()
に電話するsignalfd_siginfo
を読み取ります それからの構造 (通常、ある種の選択/ポーリング ループ内)。内容はsiginfo_t
のようになります .
どちらを使用するかは、アプリケーションの作成方法によって異なります。それらはおそらく普通の C 以外ではうまく動作しないでしょうし、Java で動作させる望みも私にはありません。また、Linux 以外では移植できません。それらは、あなたが達成しようとしていることの非常に間違った方法である可能性もあります.