2011-12-04 98 views

回答

24

的兩種方法是SA_SIGINFOsignalfd(),這允許程序接收發送有關信號非常詳細信息,包括髮送者的PID。

  • 呼叫sigaction()並傳遞給它一個struct sigaction,其具有在sa_sigaction所需信號處理程序,並在sa_flagsSA_SIGINFO標誌。使用此標誌,您的信號處理程序將收到三個參數,其中一個參數是siginfo_t結構,其中包含發件人的PID和UID。

  • 調用signalfd()並從中讀取signalfd_siginfo結構(通常在某種選擇/輪詢循環中)。內容將類似於siginfo_t

要使用哪一個取決於您的應用程序的寫入方式;他們可能無法在純C以外工作,我也沒有希望讓他們在Java中工作。它們在Linux之外也是不可移植的。他們也可能是做你正在努力實現的非常錯誤的方式。

+0

想知道你是否可以通過e寫一個C DLL並使用JAVA中的這個。 G。 JNI ... – Aconcagua

3

不,信號不作爲進程間通信通道。據我所知,沒有PID傳遞。發送PID與我所見過的所有信號無關。您可以相對確定發送信號的進程是否具有root權限,或者屬於與您的進程相同的UID。

發送信號的過程可能不再存在。如果使用kill命令而不是內置的shell,幾乎可以確定該進程不再存在。

從Java方面來看,這更加困難。該進程運行在Java虛擬機中,該虛擬機是從操作系統中抽象出來的。並非所有操作系統概念都與本機有關。

Linux特定
5

我還需要識別程序中的信號發送器,所以我把grawity的answer,並在我的程序中使用它,它運行良好。

這裏的示例代碼:

send_signal_raise。Ç

// 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 + Ç期間發送SIGINT,或CTRL + \發送SIGQUIT這將由手終止程序。

程序可以成功識別誰發送了信號。

相關問題