程序经常收到SIGTERM退出,一直没查明白SIGTERM是谁发送的。signal函数注册的处理函数只接收到signum,不知道发送者是谁。一番查找发现sigaction函数注册的sa_sigaction回调函数,有siginfo_t结构,查看man其中的si_pid就是发送者的pid。
si_pid
sigaction
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
sigaction struct:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
siginfo_t
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count;
POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor */
short si_addr_lsb; /* Least significant bit of address
(since Linux 2.6.32) */
void *si_lower; /* Lower bound when address violation
occurred (since Linux 3.19) */
void *si_upper; /* Upper bound when address violation
occurred (since Linux 3.19) */
int si_pkey; /* Protection key on PTE that caused
fault (since Linux 4.6) */
void *si_call_addr; /* Address of system call instruction
(since Linux 3.5) */
int si_syscall; /* Number of attempted system call
(since Linux 3.5) */
unsigned int si_arch; /* Architecture of attempted system call
(since Linux 3.5) */
}
example
sender.c
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include <sys/wait.h>
static void handler(int sig, siginfo_t* s, void* uctx) {
printf("si_signo=%d, si_status=%d, si_code=%d, si_pid=%ld, si_uid=%ld, si_addr=0x%lx\n",
s->si_signo, s->si_status, s->si_code, (long)s->si_pid, (long)s->si_uid, (unsigned long)s->si_addr);
}
int main(){
struct sigaction act = {
.sa_sigaction = &handler,
.sa_flags = SA_SIGINFO,
};
sigaction(SIGTERM, &act, NULL);
if (fork()==0) {
kill(getppid(),SIGTERM);
printf("myself is %d\n", getpid());
_exit(0);
}
wait(NULL);
printf("myself is %d\n", getpid());
return 0;
}
运行结果:
gcc -o sender sender.c
./sender
myself is 58579
si_signo=15, si_status=0, si_code=0, si_pid=58579, si_uid=1000, si_addr=0x3e80000e4d3
myself is 58578
文档信息
- 本文作者:seamaner
- 本文链接:https://seamaner.github.io/2022/08/16/linux-signal-sender/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)