Potřeboval jsem také identifikovat odesílatele signálu v programu, takže jsem vzal Grawityho odpověď a použil jsem ji ve svém programu, funguje to dobře.
Zde je ukázkový kód:
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;
}
Zkompilujte:
gcc -pthread -Wall send_signal_raise.c
Provést:
./a.out
Co to dělá:
Program odešle SIGINT
10krát sobě, před odesláním SIGQUIT
aby se sám ukončil.
Během jeho provádění také stiskněte CTRL +C odeslat SIGINT
nebo CTRL +\ odeslat SIGQUIT
která by program ukončila ručně.
Program mohl úspěšně identifikovat, kdo vyslal signál(y).
BCC obsahuje killsnoop
utility. Vyžaduje jádro s podporou BPF.
Výňatek z manuálové stránky 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.
Dvě metody specifické pro Linux jsou SA_SIGINFO
a signalfd()
, která umožňuje programům přijímat velmi podrobné informace o odeslaných signálech, včetně PID odesílatele.
-
Zavolejte na číslo
sigaction()
a předejte mustruct sigaction
který má požadovaný ovladač signálu vsa_sigaction
aSA_SIGINFO
příznak vsa_flags
soubor. S tímto příznakem obdrží váš operátor signálu tři argumenty, z nichž jeden jesiginfo_t
struktura obsahující PID a UID odesílatele. -
Zavolejte na číslo
signalfd()
a přečtěte sisignalfd_siginfo
struktur z něj (obvykle v nějakém druhu výběrové/poll smyčky). Obsah bude podobnýsiginfo_t
.
Který z nich použít, závisí na tom, jak je vaše aplikace napsána; pravděpodobně nebudou dobře fungovat mimo prosté C a neměl bych žádnou naději, že je zprovozním v Javě. Jsou také nepřenosné mimo Linux. Jsou také pravděpodobně velmi špatným způsobem, jak dělat to, čeho se snažíte dosáhnout.