[英]How can I tell in Linux which process sent my process a signal
我有一個獲得SIG TERM
的 java 應用程序。 我想知道發送這個信號的進程的pid。
那可能嗎?
兩個特定於 Linux 的方法是SA_SIGINFO
和signalfd()
,它們允許程序接收有關發送信號的非常詳細的信息,包括發送者的 PID。
調用sigaction()
並將struct sigaction
傳遞給它,該struct sigaction
在sa_sigaction
具有所需的信號處理程序,並在sa_flags
設置了SA_SIGINFO
標志。 使用此標志,您的信號處理程序將接收三個參數,其中一個是包含發送方 PID 和 UID 的siginfo_t
結構。
調用signalfd()
並signalfd_siginfo
讀取signalfd_siginfo
結構(通常在某種選擇/輪詢循環中)。 內容將類似於siginfo_t
。
使用哪一個取決於你的應用程序是如何編寫的; 在純 C 之外,它們可能不會很好地工作,而且我也不希望讓它們在 Java 中工作。 它們在 Linux 之外也是不可移植的。 他們也很可能是做你想要實現的事情的非常錯誤的方式。
我還需要在程序中識別信號發送者,所以我采用了grawity的答案,並在我的程序中使用它,效果很好。
這是示例代碼:
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;
}
編譯:
gcc -pthread -Wall send_signal_raise.c
執行:
./a.out
它能做什么:
程序向自身發送SIGINT
10 次,然后發送SIGQUIT
以終止自身。
此外,在執行過程中,按CTRL + C發送SIGINT
,或按CTRL + \\發送SIGQUIT
,這將手動終止程序。
該程序可以成功識別誰發送了信號。
BCC包括killsnoop
實用程序。 它需要一個支持 BPF 的內核。
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.
不,信號不打算作為進程間通信通道。 據我所知,沒有通過 PID。 發送 PID 與我見過的所有信號用途無關。 您可以相對確定發送信號的進程要么具有 root 權限,要么屬於與您的進程相同的 UID。
發送信號的進程可能不再存在。 如果使用 kill 命令而不是內置的 shell,則幾乎可以肯定該進程不再存在。
從 Java 方面來看,這更加困難。 該進程在 Java 虛擬機中運行,該虛擬機是從操作系統中抽象出來的。 並非所有操作系統概念都存在於這台機器上。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.