2011-12-04 57 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这将由手终止程序。

程序可以成功识别谁发送了信号。

相关问题