Ich musste auch den Signalsender in einem Programm identifizieren, also habe ich die Antwort von grawity genommen und in meinem Programm verwendet, es funktioniert gut.
Hier ist der Beispielcode:
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;
}
Kompilieren:
gcc -pthread -Wall send_signal_raise.c
Ausführen:
./a.out
Funktion:
Das Programm sendet SIGINT
10 mal an sich selbst, bevor SIGQUIT
gesendet wird um sich selbst zu beenden.
Drücken Sie außerdem während der Ausführung CTRL +C um SIGINT
zu senden , oder CTRL +\ um SIGQUIT
zu senden was das Programm von Hand beenden würde.
Das Programm konnte erfolgreich identifizieren, wer das/die Signal(e) gesendet hat.
BCC enthält den killsnoop
Dienstprogramm. Es erfordert einen Kernel mit BPF-Unterstützung.
Auszug aus der man-page von 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.
Zwei Linux-spezifische Methoden sind SA_SIGINFO
und signalfd()
, wodurch Programme sehr empfangen können detaillierte Informationen über gesendete Signale, einschließlich der PID des Absenders.
-
Rufen Sie
sigaction()
an und übergebe ihm einenstruct sigaction
die den gewünschten Signalhandler insa_sigaction
hat und dieSA_SIGINFO
Flag insa_flags
einstellen. Mit diesem Flag erhält Ihr Signalhandler drei Argumente, von denen eines einsiginfo_t
ist Struktur, die die PID und UID des Absenders enthält. -
Rufen Sie
signalfd()
an und lesen Siesignalfd_siginfo
Strukturen daraus (normalerweise in einer Art Select/Poll-Schleife). Der Inhalt ähneltsiginfo_t
.
Welche Sie verwenden sollten, hängt davon ab, wie Ihre Anwendung geschrieben ist. Sie werden wahrscheinlich nicht gut außerhalb von C funktionieren, und ich hätte keine Hoffnung, sie in Java zum Laufen zu bringen. Sie sind auch außerhalb von Linux nicht portierbar. Sie sind wahrscheinlich auch der völlig falsche Weg, um das zu erreichen, was Sie erreichen möchten.