J'avais aussi besoin d'identifier l'expéditeur du signal dans un programme, alors j'ai pris la réponse de Grawity et je l'ai utilisée dans mon programme, ça marche bien.
Voici l'exemple de code :
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;
}
Compiler :
gcc -pthread -Wall send_signal_raise.c
Exécuter :
./a.out
Ce qu'il fait :
Le programme envoie SIGINT
à lui-même 10 fois, avant d'envoyer SIGQUIT
se terminer.
Aussi, lors de son exécution, appuyez sur CTRL +C pour envoyer SIGINT
, ou CTRL +\ pour envoyer SIGQUIT
qui terminerait le programme à la main.
Le programme a pu identifier avec succès qui a envoyé le(s) signal(s).
BCC inclut le killsnoop
utilitaire. Il nécessite un noyau prenant en charge BPF.
Extrait de la page de manuel 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.
Deux méthodes spécifiques à Linux sont SA_SIGINFO
et signalfd()
, qui permet aux programmes de recevoir très des informations détaillées sur les signaux envoyés, y compris le PID de l'expéditeur.
-
Appelez le
sigaction()
et lui passer unstruct sigaction
qui a le gestionnaire de signal souhaité danssa_sigaction
et leSA_SIGINFO
indicateur ensa_flags
Positionner. Avec ce drapeau, votre gestionnaire de signal recevra trois arguments, dont l'un est unsiginfo_t
structure contenant le PID et l'UID de l'expéditeur. -
Appelez le
signalfd()
et liresignalfd_siginfo
structures à partir de celui-ci (généralement dans une sorte de boucle de sélection/interrogation). Le contenu sera similaire àsiginfo_t
.
Lequel utiliser dépend de la façon dont votre application est écrite ; ils ne fonctionneront probablement pas bien en dehors du C ordinaire, et je n'aurais aucun espoir de les faire fonctionner en Java. Ils sont également non portables en dehors de Linux. Ils sont également probablement la très mauvaise façon de faire ce que vous essayez d'accomplir.