Avevo anche bisogno di identificare il mittente del segnale in un programma, quindi ho preso la risposta di grawity e l'ho usata nel mio programma, funziona bene.
Ecco il codice di esempio:
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;
}
Compila:
gcc -pthread -Wall send_signal_raise.c
Esegui:
./a.out
Cosa fa:
Il programma invia SIGINT
a se stesso 10 volte, prima di inviare SIGQUIT
per terminare se stesso.
Inoltre, durante la sua esecuzione, premi CTRL +C per inviare SIGINT
o CTRL +\ per inviare SIGQUIT
che terminerebbe il programma a mano.
Il programma potrebbe identificare con successo chi ha inviato i segnali.
BCC include il killsnoop
utilità. Richiede un kernel con supporto BPF.
Estratto dalla pagina man di 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.
Due metodi specifici di Linux sono SA_SIGINFO
e signalfd()
, che consente ai programmi di ricevere molto informazioni dettagliate sui segnali inviati, incluso il PID del mittente.
-
Chiama
sigaction()
e passagli unstruct sigaction
che ha il gestore di segnale desiderato insa_sigaction
e ilSA_SIGINFO
flag insa_flags
impostare. Con questo flag, il tuo gestore di segnale riceverà tre argomenti, uno dei quali è unsiginfo_t
struttura contenente PID e UID del mittente. -
Chiama
signalfd()
e leggisignalfd_siginfo
strutture da esso (di solito in una sorta di ciclo select/poll). I contenuti saranno simili asiginfo_t
.
Quale usare dipende da come è scritta la tua applicazione; probabilmente non funzioneranno bene al di fuori del semplice C e non avrei alcuna speranza di farli funzionare in Java. Sono anche non portabili al di fuori di Linux. Probabilmente sono anche il modo molto sbagliato di fare ciò che stai cercando di ottenere.