Tôi có một ứng dụng java có SIG TERM
. Tôi muốn biết pid của quá trình gửi tín hiệu này.
Điều đó có khả thi không?Làm thế nào tôi có thể nói trong Linux rằng quá trình gửi quá trình của tôi một tín hiệu
Trả lời
Hai phương pháp cụ thể cho Linux là SA_SIGINFO
và signalfd()
, cho phép các chương trình nhận được rất thông tin chi tiết về các tín hiệu được gửi, bao gồm PID của người gửi.
Gọi
sigaction()
và vượt qua nó mộtstruct sigaction
trong đó có xử lý tín hiệu mong muốn trongsa_sigaction
vàSA_SIGINFO
cờ trongsa_flags
bộ. Với cờ này, trình xử lý tín hiệu của bạn sẽ nhận được ba đối số, một trong số đó là cấu trúcsiginfo_t
chứa PID và UID của người gửi.Gọi
signalfd()
và đọcsignalfd_siginfo
cấu trúc từ nó (thường là trong một số loại vòng chọn/thăm dò ý kiến). Nội dung sẽ tương tự nhưsiginfo_t
.
Loại nào để sử dụng tùy thuộc vào cách ứng dụng của bạn được viết; họ có thể sẽ không hoạt động tốt bên ngoài đồng bằng C, và tôi sẽ không có bất kỳ hy vọng nhận được chúng làm việc trong Java. Họ cũng không thể chuyển đổi bên ngoài Linux. Họ cũng có thể là Con đường Rất Sai lầm khi làm những gì bạn đang cố gắng đạt được.
Tự hỏi nếu bạn có thể viết một dll C và sử dụng một từ JAVA qua e. g. JNI ... – Aconcagua
Không, tín hiệu không được dự định là kênh liên lạc giữa các quá trình. Theo như tôi biết, không có PID nào được thông qua. PID gửi không liên quan đến tất cả các công dụng mà tôi đã thấy cho các tín hiệu. Bạn có thể tương đối chắc chắn rằng các quá trình gửi tín hiệu hoặc có quyền root, hoặc thuộc về cùng một UID như quá trình của bạn.
Có thể quá trình gửi tín hiệu không còn tồn tại nữa. Nếu lệnh kill được sử dụng chứ không phải là shell được tích hợp sẵn, nó gần như chắc chắn quá trình không còn tồn tại nữa.
Từ phía Java, điều này thậm chí còn khó khăn hơn. Quá trình này chạy trong một Máy ảo Java, được trừu tượng hóa từ Hệ điều hành. Không phải tất cả các khái niệm Hệ điều hành đều tồn tại với máy này.
Tôi cũng cần xác định người gửi tín hiệu trong một chương trình, vì vậy tôi lấy số answer của grawity và sử dụng nó trong chương trình của tôi, nó hoạt động tốt.
Dưới đây là đoạn code mẫu:
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;
}
Compile:
gcc -pthread -Wall send_signal_raise.c
Execute:
./a.out
Những gì nó làm:
Chương trình gửi SIGINT
đến chính nó 10 lần, trước khi gửi SIGQUIT
để chấm dứt chính nó.
Ngoài ra, trong quá trình thực hiện của nó, nhấn tổ hợp phím CTRL + C để gửi SIGINT
, hoặc CTRL +\ để gửi SIGQUIT
đó sẽ chấm dứt chương trình bằng tay.
Chương trình có thể xác định thành công ai đã gửi (các) tín hiệu.
Cảm ơn! trông giống như một câu hỏi tương tự và câu trả lời hay. – oshai