如何在Linux中告诉哪个进程向我的进程发送了一个信号

时间:2011-12-04 19:38:55

标签: linux signals

我有一个获得SIG TERM的java应用程序。我想知道发送此信号的过程的pid 这可能吗?

4 个答案:

答案 0 :(得分:30)

两种特定于Linux的方法是SA_SIGINFOsignalfd(),它们允许程序接收有关发送信号的非常详细信息,包括发送方的PID。

  • 致电sigaction()并传递struct sigaction sa_sigactionSA_SIGINFO中包含所需的信号处理程序,sa_flags中的siginfo_t标记设置为signalfd_siginfo。使用此标志,您的信号处理程序将接收三个参数,其中一个是包含发送方PID和UID的siginfo_t结构。

  • 调用signalfd()并从中读取{{1}}结构(通常在某种select / poll循环中)。内容类似于{{1}}。

使用哪一个取决于您的应用程序的编写方式;它们可能在普通C之外不能正常工作,我也没有希望让它们在Java中工作。它们在Linux之外也是不可移植的。他们也可能是你正在努力实现目标的非常错误的方式。

答案 1 :(得分:9)

我还需要在程序中识别信号发送者,所以我使用了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以终止自身之前,程序会将SIGQUIT发送给自己10次。

此外,在执行期间,按 CTRL + C 发送SIGINT,或 CTRL + \ < / kbd>发送SIGQUIT手动终止程序。

该程序可以成功识别发送信号的人。

答案 2 :(得分:1)

不,信号不是作为进程间通信通道。据我所知,没有PID通过。发送PID与我在信号中看到的所有用途无关。您可以相对确定发送信号的进程具有root权限,或者属于与进程相同的UID。

发送信号的过程可能不再存在。如果使用kill命令而不是内置shell,则几乎可以肯定该进程不再存在。

从Java方面来看,这更加困难。该过程在Java虚拟机中运行,该虚拟机从操作系统中抽象出来。并非此计算机存在所有操作系统概念。

答案 3 :(得分:1)

BCC包括android:animateLayoutChanges="true"实用程序。它需要具有BPF支持的内核。

摘录自killsnoop (8) man-page

killsnoop