2011-12-04 50 views

Trả lời

24

Hai phương pháp cụ thể cho Linux là SA_SIGINFOsignalfd(), 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ột struct sigaction trong đó có xử lý tín hiệu mong muốn trong sa_sigactionSA_SIGINFO cờ trong sa_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úc siginfo_t chứa PID và UID của người gửi.

  • Gọi signalfd() và đọc signalfd_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.

+0

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

3

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.

5

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ác vấn đề liên quan