SIG TERM
を取得したJavaアプリケーションがあります。このシグナルを送信したプロセスのpidを知りたいです。
それは可能ですか?
Linux固有の2つのメソッドは SA_SIGINFO
と signalfd()
で、プログラムがvery詳細情報を受信できるようにします。送信者のPIDを含む、送信された信号について。
sigaction()
を呼び出し、struct sigaction
に目的のシグナルハンドラーがあり、sa_sigaction
にSA_SIGINFO
フラグが設定されているsa_flags
を渡します。このフラグを使用すると、シグナルハンドラーは3つの引数を受け取ります。そのうちの1つは、送信者のPIDとUIDを含むsiginfo_t
構造体です。
signalfd()
を呼び出し、そこからsignalfd_siginfo
構造を読み取ります(通常、ある種の選択/ポーリングループで)。内容はsiginfo_t
のようになります。
どちらを使用するかは、アプリケーションの作成方法によって異なります。それらはおそらくプレーンCの外ではうまく機能しないでしょうし、Javaでそれらを機能させることは期待できません。また、Linux以外では移植できません。彼らはまた、あなたが達成しようとしていることを行うための非常に間違った方法である可能性があります。
また、プログラムでシグナルの送信者を特定する必要があったので、grawityの answer を取得して、プログラムで使用しました。これはうまく機能します。
サンプルコードは次のとおりです。
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+CSIGINT
を送信する、または CTRL+\SIGQUIT
を送信すると、プログラムが手動で終了します。
プログラムは、誰が信号を送信したかを正常に識別できました。
いいえ、シグナルはプロセス間通信チャネルとして意図されていません。私の知る限り、PIDは渡されていません。送信PIDは、私がシグナルについて見たすべての用途とは無関係です。シグナルを送信するプロセスがroot権限を持っているか、プロセスと同じUIDに属していることを比較的確信できます。
信号を送信したプロセスが存在しない可能性があります。 Shell組み込みではなくkillコマンドが使用された場合、プロセスが存在しなくなったことはほぼ確実です。
Java側から見ると、これはさらに困難です。プロセスは、オペレーティングシステムから抽象化されたJava仮想マシンで実行されます。すべてのオペレーティングシステムの概念ではありません。このマシンに存在します。